home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Tools - Objects / MacApp / MacApp 2.0 CD Release / MacApp 2.0 (Many Libraries) / Libraries / UGridView.inc1.p < prev    next >
Encoding:
Text File  |  1990-03-27  |  72.7 KB  |  2,784 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UGridView.inc1.p }
  4. { Copyright © 1987-1990 by Apple Computer Inc. All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S GVInit}
  8.  
  9. PROCEDURE InitUGridView;
  10.  
  11.     BEGIN
  12.     IF qTemplateViews THEN
  13.         BEGIN
  14.         { So the linker doesn't dead strip these }
  15.         IF gDeadStripSuppression THEN
  16.             BEGIN
  17.             IF Member(TObject(NIL), TGridView) THEN;
  18.             IF Member(TObject(NIL), TTextGridView) THEN;
  19.             IF Member(TObject(NIL), TTextListView) THEN;
  20.             END;
  21.  
  22.         RegisterStdType('TGridView', kStdGridView);
  23.         RegisterStdType('TTextGridView', kStdTextGridView);
  24.         RegisterStdType('TTextListView', kStdTextListView);
  25.         END;
  26.  
  27.     pPixelsToHighlight := MakeNewRgn;
  28.     pPreviousSelection := MakeNewRgn;
  29.     pDifference := MakeNewRgn;
  30.     pVisibleCells := MakeNewRgn;
  31.     pInvalidateRgn := MakeNewRgn;
  32.     gUGridViewInitialized := TRUE;
  33.     END;
  34.  
  35. {--------------------------------------------------------------------------------------------------}
  36. {$S GVOpen}
  37.  
  38. PROCEDURE TRunArray.IRunArray;
  39.  
  40.     BEGIN
  41.     IObject;
  42.  
  43.     fNoOfItems := 0;
  44.     fNoOfChunks := 0;
  45.     fTotal := 0;
  46.     fLastItem := 0;
  47.     fLastChunk := 0;
  48.     fLastTotal := 0;
  49.     fLastIndex := 1;
  50.     fChunks := ChunkArrayHandle(NewPermHandle(0));
  51.     FailNIL(fChunks);
  52.     END;
  53.  
  54. {--------------------------------------------------------------------------------------------------}
  55. {$S GVClose}
  56.  
  57. PROCEDURE TRunArray.Free; OVERRIDE;
  58.  
  59.     BEGIN
  60.     Handle(fChunks) := DisposeIfHandle(fChunks);        { Blow chunks }
  61.  
  62.     INHERITED Free;
  63.     END;
  64.  
  65. {--------------------------------------------------------------------------------------------------}
  66. {$S GVNonRes}
  67.  
  68. PROCEDURE TRunArray.DeleteItems(firstItem, noOfItems: INTEGER);
  69.  
  70.     VAR
  71.         offset:             LONGINT;
  72.         result:             LONGINT;
  73.         i:                    INTEGER;
  74.         num:                INTEGER;
  75.         theTotal:            LONGINT;
  76.         Index:                INTEGER;
  77.  
  78.     BEGIN
  79.     IF NOT FindChunk(firstItem, num, Index, theTotal) THEN
  80.         BEGIN
  81.         {$IFC qDebug}
  82.         ProgramBreak(ConcatNumber('Unable to find chunk for item ', firstItem));
  83.         {$ENDC}
  84.         EXIT(DeleteItems);
  85.         END;
  86.  
  87.     FOR i := 1 TO noOfItems DO
  88.         BEGIN
  89.         fTotal := fTotal - fChunks^^[num].value;
  90.  
  91.         fChunks^^[num].count := fChunks^^[num].count - 1;
  92.  
  93.         IF (fChunks^^[num].count < Index) THEN
  94.             BEGIN
  95.             IF (fChunks^^[num].count = 0) THEN
  96.                 BEGIN
  97.                 { need to delete that chunk }
  98.                 offset := IntMultiply(num, SIZEOF(RunArrayChunk));
  99.                 result := Munger(Handle(fChunks), offset, NIL, SIZEOF(RunArrayChunk), @result, 0);
  100.                 FailMemError;
  101.                 fNoOfChunks := fNoOfChunks - 1;
  102.  
  103.                 { Thanks JDR 10/28/89 }
  104.                 { see if we can consolidate chunks }
  105.                 IF (num > 0) & (num < fNoOfChunks) & (fChunks^^[num - 1].value =
  106.                    fChunks^^[num].value) THEN
  107.                     BEGIN
  108.                     Index := fChunks^^[num - 1].count + 1;
  109.                     fChunks^^[num - 1].count := fChunks^^[num - 1].count + fChunks^^[num].count;
  110.                     { need to delete that chunk }
  111.                     result := Munger(Handle(fChunks), offset, NIL, SIZEOF(RunArrayChunk), @result,
  112.                                      0);
  113.                     FailMemError;
  114.                     num := num - 1;
  115.                     fNoOfChunks := fNoOfChunks - 1;
  116.                     END;
  117.                 END
  118.             ELSE
  119.                 num := num + 1;
  120.             Index := 1;
  121.             END;
  122.         END;
  123.  
  124.     fNoOfItems := fNoOfItems - noOfItems;
  125.  
  126.     { reset the cache }
  127.     fLastItem := 0;
  128.     fLastChunk := 0;
  129.     fLastTotal := 0;
  130.     fLastIndex := 1;
  131.     END;
  132.  
  133. {--------------------------------------------------------------------------------------------------}
  134. {$S GVFields}
  135.  
  136. PROCEDURE TRunArray.Fields(PROCEDURE DoToField(fieldName: Str255;
  137.                                                fieldAddr: Ptr;
  138.                                                fieldType: INTEGER)); OVERRIDE;
  139.  
  140.     VAR
  141.         aString, numString: Str255;
  142.         i:                    INTEGER;
  143.  
  144.     BEGIN
  145.     DoToField('TRunArray', NIL, bClass);
  146.     DoToField('fNoOfItems', @fNoOfItems, bInteger);
  147.     DoToField('fNoOfChunks', @fNoOfChunks, bInteger);
  148.     DoToField('fTotal', @fTotal, bLongInt);
  149.     DoToField('fLastItem', @fLastItem, bInteger);
  150.     DoToField('fLastChunk', @fLastChunk, bInteger);
  151.     DoToField('fLastTotal', @fLastTotal, bLongInt);
  152.     DoToField('fLastIndex', @fLastIndex, bInteger);
  153.  
  154.   { !!! When these come from the dynamic area remember to put the field in the DynamicField method }
  155.     FOR i := 0 TO fNoOfChunks - 1 DO
  156.         BEGIN
  157.         NumToString(i, numString);
  158.         aString := Concat('count[', numString, ']');
  159.         DoToField(aString, @fChunks^^[i].count, bInteger);
  160.         aString := Concat('value[', numString, ']');
  161.         DoToField(aString, @fChunks^^[i].value, bInteger);
  162.         END;
  163.     INHERITED Fields(DoToField);
  164.     END;
  165.  
  166. {--------------------------------------------------------------------------------------------------}
  167. {$S GVRes}
  168. {$Push} {$OV-}                                            {!!!SRF remove this line when the compiler
  169.                                                          gets smarter }
  170.  
  171. FUNCTION TRunArray.FindChunk(item: INTEGER;
  172.                              VAR chunk, indexInChunk: INTEGER;
  173.                              VAR theTotal: LONGINT): BOOLEAN;
  174.  
  175.     VAR
  176.         thisItem:            INTEGER;
  177.         count:                INTEGER;
  178.         delta:                INTEGER;
  179.  
  180.     BEGIN
  181.     IF (fNoOfChunks <= 0) | (item > fNoOfItems) | (item <= 0) THEN
  182.         BEGIN
  183.         chunk := 0;
  184.         theTotal := 0;
  185.         indexInChunk := 0;
  186.         FindChunk := FALSE;
  187.         item := 0;
  188.         END
  189.     ELSE IF (item = fLastItem) THEN
  190.         BEGIN                                            { check for the very easy case }
  191.         chunk := fLastChunk;
  192.         theTotal := fLastTotal;
  193.         indexInChunk := fLastIndex;
  194.         FindChunk := TRUE;
  195.         END
  196.     ELSE
  197.         BEGIN
  198.         delta := ABS(item - fLastItem);
  199.  
  200.         IF (delta >= item) | (item <= fChunks^^[0].count) THEN
  201.             BEGIN                                        { start from the first chunk }
  202.             chunk := 0;
  203.             theTotal := 0;
  204.             thisItem := 0;
  205.             END
  206.         ELSE IF (delta > (fNoOfItems - item + 1)) THEN
  207.             BEGIN                                        { start from the end chunk }
  208.             chunk := fNoOfChunks - 1;
  209.             count := fChunks^^[chunk].count;
  210.             theTotal := fTotal - IntMultiply(count, fChunks^^[chunk].value);
  211.             thisItem := fNoOfItems - count;
  212.             END
  213.         ELSE
  214.             BEGIN                                        { start from the previous values }
  215.             chunk := fLastChunk;
  216.             theTotal := fLastTotal;
  217.             thisItem := fLastItem - fLastIndex;
  218.             END;
  219.  
  220.         IF item > thisItem THEN
  221.             BEGIN
  222.             WHILE ((thisItem + fChunks^^[chunk].count) < item) DO
  223.                 BEGIN
  224.                 count := fChunks^^[chunk].count;
  225.                 theTotal := theTotal + IntMultiply(count, fChunks^^[chunk].value);
  226.                 thisItem := thisItem + count;
  227.                 chunk := chunk + 1;
  228.                 END;
  229.             END
  230.         ELSE
  231.             BEGIN
  232.             REPEAT
  233.                 chunk := chunk - 1;
  234.                 count := fChunks^^[chunk].count;
  235.                 theTotal := theTotal - IntMultiply(count, fChunks^^[chunk].value);
  236.                 thisItem := thisItem - count;
  237.             UNTIL (thisItem < item);
  238.             END;
  239.         indexInChunk := item - thisItem;
  240.         FindChunk := TRUE;
  241.         END;
  242.     { cache the last values }
  243.     fLastItem := item;
  244.     fLastChunk := chunk;
  245.     fLastTotal := theTotal;
  246.     fLastIndex := indexInChunk;
  247.     END;
  248. {$Pop}
  249.  
  250. {--------------------------------------------------------------------------------------------------}
  251. {$S GVRes}
  252.  
  253. FUNCTION TRunArray.FindItem(theTotal: LONGINT): INTEGER;
  254.  
  255.     VAR
  256.         i:                    INTEGER;
  257.         runningCount:        INTEGER;
  258.  
  259.     BEGIN
  260.     FindItem := 0;
  261.     IF (theTotal >= 0) & (theTotal <= fTotal) & (fNoOfChunks > 0) THEN
  262.         IF fNoOfChunks = 1 THEN
  263.             BEGIN
  264.             IF fChunks^^[0].value > 0 THEN
  265.                 FindItem := Min(((theTotal - 1) DIV fChunks^^[0].value) + 1, fNoOfItems);
  266.             END
  267.         ELSE IF theTotal = 0 THEN
  268.             FindItem := 1
  269.         ELSE
  270.             BEGIN
  271.             theTotal := theTotal + 1;
  272.             runningCount := 0;
  273.             FOR i := 0 TO fNoOfChunks - 1 DO
  274.                 WITH fChunks^^[i] DO
  275.                     BEGIN
  276.                     theTotal := theTotal - IntMultiply(value, count);
  277.                     runningCount := runningCount + count;
  278.                     IF theTotal <= 0 THEN
  279.                         BEGIN
  280.                         FindItem := runningCount + (theTotal DIV value);
  281.                         EXIT(FindItem);
  282.                         END;
  283.                     END;
  284.             FindItem := fNoOfItems;
  285.             END;
  286.     END;
  287.  
  288. {--------------------------------------------------------------------------------------------------}
  289. {$S GVRes}
  290.  
  291. FUNCTION TRunArray.GetValue(item: INTEGER): INTEGER;
  292.  
  293.     VAR
  294.         num:                INTEGER;
  295.         theTotal:            LONGINT;
  296.         Index:                INTEGER;
  297.  
  298.     BEGIN
  299.     IF fNoOfChunks = 1 THEN
  300.         GetValue := fChunks^^[0].value
  301.     ELSE IF FindChunk(item, num, Index, theTotal) THEN
  302.         GetValue := fChunks^^[num].value
  303.     ELSE
  304.         GetValue := 0;
  305.     END;
  306.  
  307. {--------------------------------------------------------------------------------------------------}
  308. {$S GVRes}
  309.  
  310. PROCEDURE TRunArray.InsertItems(firstItem, noOfItems, value: INTEGER);
  311.  
  312.     VAR
  313.         num:                INTEGER;
  314.         theTotal:            LONGINT;
  315.         Index:                INTEGER;
  316.         oldSize:            LONGINT;
  317.         result:             LONGINT;
  318.         tempChunks:         RECORD
  319.             chunk1:             RunArrayChunk;
  320.             chunk2:             RunArrayChunk;
  321.             END;
  322.  
  323.     BEGIN
  324.     { Check if we can just increment the last size count }
  325.     IF (firstItem > fNoOfItems) & (fNoOfChunks > 0) & (fChunks^^[fNoOfChunks - 1].value =
  326.        value) THEN
  327.  
  328.         fChunks^^[fNoOfChunks - 1].count := fChunks^^[fNoOfChunks - 1].count + noOfItems
  329.  
  330.         { check if we can increment any size count }
  331.     ELSE IF FindChunk(firstItem, num, Index, theTotal) & (fChunks^^[num].value = value) THEN
  332.  
  333.         fChunks^^[num].count := fChunks^^[num].count + noOfItems
  334.  
  335.         { check if this would actually fit as the last item in the previous chunk }
  336.         { Thanks Martin Frické, 10/31/89 }
  337.     ELSE IF (num > 0) & (Index = 1) & (fChunks^^[num - 1].value = value) THEN
  338.         fChunks^^[num - 1].count := fChunks^^[num - 1].count + noOfItems
  339.  
  340.         { We need to create a new chunk, possibly two }
  341.     ELSE
  342.         BEGIN
  343.         oldSize := GetHandleSize(Handle(fChunks));
  344.         tempChunks.chunk1.value := value;
  345.         tempChunks.chunk1.count := noOfItems;
  346.  
  347.         IF (Index <= 1) | (firstItem > fNoOfItems) THEN
  348.             BEGIN                                        { need to add one chunk }
  349.             IF (firstItem > fNoOfItems) THEN
  350.                 num := fNoOfChunks;                     { add a row on the end }
  351.  
  352.             result := Munger(Handle(fChunks), IntMultiply(num, SIZEOF(RunArrayChunk)), NIL, 0,
  353.                              @tempChunks, SIZEOF(RunArrayChunk));
  354.             FailMemError;
  355.             fNoOfChunks := fNoOfChunks + 1;
  356.             END
  357.         ELSE
  358.             BEGIN
  359.             { need to add two }
  360.             tempChunks.chunk2.count := fChunks^^[num].count - Index + 1;
  361.             tempChunks.chunk2.value := fChunks^^[num].value;
  362.             fChunks^^[num].count := Index - 1;
  363.             result := Munger(Handle(fChunks), IntMultiply(num + 1, SIZEOF(RunArrayChunk)), NIL, 0,
  364.                              @tempChunks, 2 * SIZEOF(RunArrayChunk));
  365.             FailMemError;
  366.             fNoOfChunks := fNoOfChunks + 2;
  367.             END;
  368.         IF GetHandleSize(Handle(fChunks)) <= oldSize THEN
  369.             Failure(memFullErr, 0);
  370.         END;
  371.  
  372.     { reset the cache }
  373.     fLastItem := 0;
  374.     fLastChunk := 0;
  375.     fLastTotal := 0;
  376.     fLastIndex := 1;
  377.  
  378.     fNoOfItems := fNoOfItems + noOfItems;
  379.     fTotal := fTotal + IntMultiply(noOfItems, value);
  380.     END;
  381.  
  382. {--------------------------------------------------------------------------------------------------}
  383. {$S GVRes}
  384.  
  385. FUNCTION TRunArray.SumValues(firstItem, noOfItems: INTEGER): LONGINT;
  386.  
  387.     VAR
  388.         chunk:                INTEGER;
  389.         indexInChunk:        INTEGER;
  390.         total:                LONGINT;
  391.         precedingTotal:     LONGINT;
  392.  
  393.     BEGIN
  394.     SumValues := 0;
  395.  
  396.     IF fNoOfChunks = 1 THEN
  397.         SumValues := IntMultiply(noOfItems, fChunks^^[0].value)
  398.     ELSE IF firstItem = 1 THEN
  399.         BEGIN
  400.         IF FindChunk(noOfItems, chunk, indexInChunk, total) THEN
  401.             SumValues := total + IntMultiply(indexInChunk, fChunks^^[chunk].value);
  402.         END
  403.     ELSE IF FindChunk(firstItem, chunk, indexInChunk, total) THEN
  404.         BEGIN
  405.         precedingTotal := total + IntMultiply(indexInChunk - 1, fChunks^^[chunk].value);
  406.         IF FindChunk(firstItem + noOfItems - 1, chunk, indexInChunk, total) THEN
  407.             SumValues := total + IntMultiply(indexInChunk, fChunks^^[chunk].value) - precedingTotal;
  408.         END;
  409.     END;
  410.  
  411. {--------------------------------------------------------------------------------------------------}
  412. {$S GVOpen}
  413.  
  414. PROCEDURE TGridView.IGridView(itsDocument: TDocument;    { Its document }
  415.                               itsSuperView: TView;        { Its parent view }
  416.                               itsLocation: VPoint;        { Top, Left in parent's coords }
  417.                               itsSize: VPoint;            { Ignored for SizeVariable}
  418.                               itsHSizeDet, itsVSizeDet: SizeDeterminer; { Size determiners }
  419.                               numOfRows: INTEGER;        { Number of rows initially }
  420.                               numOfCols: INTEGER;        { Number of columns initially }
  421.                               rowHeight: INTEGER;        { Height of initial rows }
  422.                               colWidth: INTEGER;        { Height of initial columns }
  423.                               adornRows: BOOLEAN;        { Adornment for Rows? }
  424.                               adornCols: BOOLEAN;        { Adornment for Columns? }
  425.                               rowInset: INTEGER;        { horizontal space between cells }
  426.                               colInset: INTEGER;        { vertical space between cells }
  427.                               singleSelection: BOOLEAN); { single cell selection? }
  428.  
  429.     VAR
  430.         aRunArray:            TRunArray;
  431.  
  432.     BEGIN
  433.     {$IFC qDebug}
  434.     IF NOT gUGridViewInitialized THEN
  435.         BEGIN
  436.         ProgramBreak('InitUGridView must be called before creating a grid view.');
  437.         Failure(noErr, 0);
  438.         END;
  439.     {$ENDC}
  440.  
  441.     fNumOfRows := 0;
  442.     fNumOfCols := 0;
  443.  
  444.     fAdornRows := adornRows;
  445.     fAdornCols := adornCols;
  446.  
  447.     { Make sure the insets are evenly divided between top/bottom or left/right }
  448.     IF ODD(rowInset) THEN
  449.         fRowInset := rowInset + 1
  450.     ELSE
  451.         fRowInset := rowInset;
  452.  
  453.     IF ODD(colInset) THEN
  454.         fColInset := colInset + 1
  455.     ELSE
  456.         fColInset := colInset;
  457.  
  458.     New(aRunArray);
  459.     FailNIL(aRunArray);
  460.     fColWidths := aRunArray;
  461.     fColWidths.IRunArray;
  462.  
  463.     New(aRunArray);
  464.     FailNIL(aRunArray);
  465.     fRowHeights := aRunArray;
  466.     fRowHeights.IRunArray;
  467.  
  468.     IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
  469.  
  470.     fSelections := MakeNewRgn;                            { region to hold current selections }
  471.     fHLRegion := MakeNewRgn;                            { region to hold current highlighted cells }
  472.     fTempSelections := MakeNewRgn;                        { used by SetSelectionRect }
  473.  
  474.     fSingleSelection := singleSelection;
  475.  
  476.     IF (numOfCols > 0) THEN
  477.         InsColFirst(numOfCols, colWidth);
  478.     IF (numOfRows > 0) THEN
  479.         InsRowFirst(numOfRows, rowHeight);
  480.  
  481.     END;
  482.  
  483. {--------------------------------------------------------------------------------------------------}
  484. {$S GVOpen}
  485.  
  486. PROCEDURE TGridView.IRes(itsDocument: TDocument;
  487.                          itsSuperView: TView;
  488.                          VAR itsParams: Ptr); OVERRIDE;
  489.  
  490.     VAR
  491.         aRunArray:            TRunArray;
  492.  
  493.     BEGIN
  494.     {$IFC qDebug}
  495.     IF NOT gUGridViewInitialized THEN
  496.         BEGIN
  497.         ProgramBreak('InitUGridView must be called before creating a grid view.');
  498.         Failure(noErr, 0);
  499.         END;
  500.     {$ENDC}
  501.  
  502.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  503.  
  504.     WITH GridViewTemplatePtr(itsParams)^ DO
  505.         BEGIN
  506.         fNumOfRows := 0;
  507.         fNumOfCols := 0;
  508.  
  509.         fAdornRows := adornRows;
  510.         fAdornCols := adornCols;
  511.  
  512.         { Make sure the insets are evenly divided between top/bottom or left/right }
  513.         IF ODD(rowInset) THEN
  514.             fRowInset := rowInset + 1
  515.         ELSE
  516.             fRowInset := rowInset;
  517.  
  518.         IF ODD(colInset) THEN
  519.             fColInset := colInset + 1
  520.         ELSE
  521.             fColInset := colInset;
  522.  
  523.         fSingleSelection := singleSelection;
  524.  
  525.         New(aRunArray);
  526.         FailNIL(aRunArray);
  527.         fColWidths := aRunArray;
  528.         fColWidths.IRunArray;
  529.  
  530.         New(aRunArray);
  531.         FailNIL(aRunArray);
  532.         fRowHeights := aRunArray;
  533.         fRowHeights.IRunArray;
  534.  
  535.         fSelections := MakeNewRgn;                        { region to hold current selections }
  536.         fHLRegion := MakeNewRgn;                        { region to hold current highlighted cells }
  537.         fTempSelections := MakeNewRgn;                    { used by SetSelectionRect }
  538.  
  539.         IF (numOfCols > 0) THEN
  540.             InsColFirst(numOfCols, colWidth);
  541.         IF (numOfRows > 0) THEN
  542.             InsRowFirst(numOfRows, rowHeight);
  543.  
  544.         END;
  545.  
  546.     OffsetPtr(itsParams, SIZEOF(GridViewTemplate));
  547.     END;
  548.  
  549. {--------------------------------------------------------------------------------------------------}
  550. {$S GVNonRes}
  551.  
  552. PROCEDURE TGridView.WRes(theResource: ViewRsrcHndl;
  553.                          VAR itsParams: Ptr); OVERRIDE;
  554.  
  555.     VAR
  556.         gvPtr:                GridViewTemplatePtr;
  557.  
  558.     BEGIN
  559.     INHERITED WRes(theResource, itsParams);
  560.  
  561.     gvPtr := GridViewTemplatePtr(ExpandPtr(theResource, itsParams, SIZEOF(GridViewTemplate)));
  562.  
  563.     WITH gvPtr^ DO
  564.         BEGIN
  565.         numOfRows := fNumOfRows;
  566.         numOfCols := fNumOfCols;
  567.         IF fNumOfRows > 0 THEN
  568.             rowHeight := GetRowHeight(1)
  569.         ELSE
  570.             rowHeight := 0;
  571.         IF fNumOfCols > 0 THEN
  572.             colWidth := GetColWidth(1)
  573.         ELSE
  574.             colWidth := 0;
  575.         rowInset := fRowInset;
  576.         colInset := fColInset;
  577.         adornRows := fAdornRows;
  578.         adornCols := fAdornCols;
  579.         singleSelection := fSingleSelection;
  580.         END;
  581.     END;
  582.  
  583. {--------------------------------------------------------------------------------------------------}
  584. {$S GVNonRes}
  585.  
  586. PROCEDURE TGridView.WriteRes(theResource: ViewRsrcHndl;
  587.                              VAR itsParams: Ptr); OVERRIDE;
  588.  
  589.     BEGIN
  590.     gWResSignature := 'grid'; gWResType := 'TGridView';
  591.     WRes(theResource, itsParams);
  592.     END;
  593.  
  594. {--------------------------------------------------------------------------------------------------}
  595. {$S GVClose}
  596.  
  597. PROCEDURE TGridView.Free; OVERRIDE;
  598.  
  599.     BEGIN
  600.     IF fSelections <> NIL THEN
  601.         DisposeRgn(fSelections);                        { Dispose regions }
  602.     fSelections := NIL;
  603.  
  604.     IF fHLRegion <> NIL THEN
  605.         DisposeRgn(fHLRegion);
  606.     fHLRegion := NIL;
  607.  
  608.     IF fTempSelections <> NIL THEN
  609.         DisposeRgn(fTempSelections);
  610.     fTempSelections := NIL;
  611.  
  612.     FreeIfObject(fColWidths);
  613.     fColWidths := NIL;
  614.  
  615.     FreeIfObject(fRowHeights);
  616.     fRowHeights := NIL;
  617.  
  618.     INHERITED Free;
  619.     END;
  620.  
  621. {--------------------------------------------------------------------------------------------------}
  622. {$S GVRes}
  623.  
  624. PROCEDURE TGridView.AllCellsDo(PROCEDURE DoToCell(aCell: GridCell));
  625.  
  626.     VAR
  627.         bounds:             Rect;
  628.  
  629.     BEGIN
  630.     SetRect(bounds, 1, 1, fNumOfCols, fNumOfRows);
  631.     EachCellDo(bounds.topLeft, bounds.botRight, DoToCell);
  632.     END;
  633.  
  634. {--------------------------------------------------------------------------------------------------}
  635. {$S GVRes}
  636.  
  637. PROCEDURE TGridView.AdornCol(aCol: INTEGER;
  638.                              area: Rect);
  639.  
  640.     BEGIN
  641.     END;
  642.  
  643. {--------------------------------------------------------------------------------------------------}
  644. {$S GVRes}
  645.  
  646. PROCEDURE TGridView.AdornRow(aRow: INTEGER;
  647.                              area: Rect);
  648.  
  649.     BEGIN
  650.     END;
  651.  
  652. {--------------------------------------------------------------------------------------------------}
  653. {$S GVRes}
  654.  
  655. PROCEDURE TGridView.CalcMinSize(VAR minSize: VPoint); OVERRIDE;
  656.  
  657.     BEGIN
  658.     INHERITED CalcMinSize(minSize);
  659.  
  660.     { Set the amount of room needed for that many items }
  661.     minSize.v := fRowHeights.fTotal;
  662.     minSize.h := fColWidths.fTotal;
  663.     END;
  664.  
  665. {--------------------------------------------------------------------------------------------------}
  666. {$S GVRes}
  667.  
  668. FUNCTION TGridView.CanSelectCell(aCell: GridCell): BOOLEAN;
  669.  
  670.     BEGIN
  671.     WITH aCell DO
  672.         CanSelectCell := (h >= 1) & (v >= 1) & (h <= fNumOfCols) & (v <= fNumOfRows);
  673.     END;
  674.  
  675. {--------------------------------------------------------------------------------------------------}
  676. {$S GVRes}
  677.  
  678. PROCEDURE TGridView.CellToVRect(aCell: GridCell;
  679.                                 VAR aRect: VRect);
  680.  
  681.     VAR
  682.         width, height:        INTEGER;
  683.  
  684.     BEGIN
  685.     IF (aCell.h < 1) | (aCell.v < 1) | (aCell.h > fNumOfCols) | (aCell.v > fNumOfRows) THEN
  686.         BEGIN
  687.         {$IFC qRangeCheck AND qDebug}
  688.         Writeln('aCell.h = ', aCell.h: 6, ' fNumOfCols = ', fNumOfCols: 6);
  689.         Writeln('aCell.v = ', aCell.v: 6, ' fNumOfRows = ', fNumOfRows: 6);
  690.         ProgramBreak('Range Check in CellToVRect');
  691.         {$ENDC}
  692.         aRect := gZeroVRect;
  693.         END
  694.     ELSE                                                { all the params look OK }
  695.         BEGIN
  696.         width := fColWidths.GetValue(aCell.h);
  697.         IF fColWidths.fNoOfChunks = 1 THEN
  698.             aRect.left := IntMultiply(width, aCell.h - 1)
  699.         ELSE
  700.             aRect.left := fColWidths.SumValues(1, aCell.h - 1);
  701.         aRect.right := aRect.left + width;
  702.  
  703.         height := fRowHeights.GetValue(aCell.v);
  704.         IF fRowHeights.fNoOfChunks = 1 THEN
  705.             aRect.top := IntMultiply(height, aCell.v - 1)
  706.         ELSE
  707.             aRect.top := fRowHeights.SumValues(1, aCell.v - 1);
  708.         aRect.bottom := aRect.top + height;
  709.         END;
  710.     END;
  711.  
  712. {--------------------------------------------------------------------------------------------------}
  713. {$S GVRes}
  714.  
  715. PROCEDURE TGridView.ColToVRect(aCol: INTEGER;
  716.                                numOfCols: INTEGER;
  717.                                VAR aRect: VRect);
  718.  
  719.     VAR
  720.         width:                LONGINT;
  721.         leftEdge:            LONGINT;
  722.  
  723.     BEGIN
  724.     IF (aCol < 1) | (numOfCols < 1) | (aCol + numOfCols - 1 > fNumOfCols) THEN
  725.         BEGIN
  726.         {$IFC qDebug AND qRangeCheck}
  727.         Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  728.         ProgramBreak('Range Check in ColToVRect');
  729.         {$ENDC}
  730.         SetVRect(aRect, 0, 0, 0, 0);
  731.         END
  732.     ELSE                                                { all the params look OK }
  733.         BEGIN
  734.         IF (fColWidths.fNoOfChunks = 1) THEN            { only one column height }
  735.             BEGIN
  736.             width := GetColWidth(1);
  737.             leftEdge := IntMultiply(width, aCol - 1);
  738.             width := IntMultiply(width, numOfCols);
  739.             END
  740.         ELSE
  741.             BEGIN
  742.             leftEdge := fColWidths.SumValues(1, aCol - 1);
  743.             width := fColWidths.SumValues(aCol, numOfCols);
  744.             END;
  745.  
  746.         SetVRect(aRect, leftEdge, 0, leftEdge + width, fRowHeights.fTotal);
  747.         END;
  748.     END;
  749.  
  750. {--------------------------------------------------------------------------------------------------}
  751. {$S GVRes}
  752.  
  753. PROCEDURE TGridView.CellsToPixels(theCells, thePixels: RgnHandle);
  754.  
  755.     VAR
  756.         cellBounds:         Rect;
  757.         visibleRect:        Rect;
  758.         visibleVRect:        VRect;
  759.         visibleCells:        Rect;
  760.         stripRect:            Rect;
  761.         aCell:                GridCell;
  762.         row, col:            INTEGER;
  763.         pixels:             VRect;
  764.         prevPixels:         VRect;
  765.         prevstripRect:        Rect;
  766.         direction:            VHSelect;
  767.         startOfStrip:        INTEGER;
  768.  
  769.     PROCEDURE AddStrip(endOfStrip: INTEGER);
  770.  
  771.         BEGIN
  772.         IF direction = v THEN
  773.             SetRect(stripRect, col, startOfStrip, col, endOfStrip)
  774.         ELSE
  775.             SetRect(stripRect, startOfStrip, row, endOfStrip, row);
  776.  
  777.         {$IFC qDebug}
  778.         IF gIntenseDebugging THEN
  779.             BEGIN
  780.             WrLblRect('Adding cells', stripRect);
  781.             Writeln;
  782.             END;
  783.         {$ENDC}
  784.  
  785.         IF stripRect.top = prevstripRect.top THEN
  786.             pixels.top := prevPixels.top
  787.         ELSE
  788.             BEGIN
  789.             pixels.top := fRowHeights.SumValues(1, stripRect.top - 1);
  790.             prevPixels.top := pixels.top;
  791.             END;
  792.         IF stripRect.bottom = prevstripRect.bottom THEN
  793.             pixels.bottom := prevPixels.bottom
  794.         ELSE
  795.             BEGIN
  796.             IF stripRect.bottom = stripRect.top THEN
  797.                 pixels.bottom := pixels.top + fRowHeights.GetValue(stripRect.bottom)
  798.             ELSE
  799.                 pixels.bottom := fRowHeights.SumValues(1, stripRect.bottom);
  800.             prevPixels.bottom := pixels.bottom;
  801.             END;
  802.         IF stripRect.left = prevstripRect.left THEN
  803.             pixels.left := prevPixels.left
  804.         ELSE
  805.             BEGIN
  806.             pixels.left := fColWidths.SumValues(1, stripRect.left - 1);
  807.             prevPixels.left := pixels.left;
  808.             END;
  809.         IF stripRect.right = prevstripRect.right THEN
  810.             pixels.right := prevPixels.right
  811.         ELSE
  812.             BEGIN
  813.             IF stripRect.right = stripRect.left THEN
  814.                 pixels.right := pixels.left + fColWidths.GetValue(stripRect.right)
  815.             ELSE
  816.                 pixels.right := fColWidths.SumValues(1, stripRect.right);
  817.             prevPixels.right := pixels.right;
  818.             END;
  819.  
  820.         ViewToQDRect(pixels, gTempRgn^^.rgnBBox);        { Sneaky, but we know gTempRgn is
  821.                                                          rectangular }
  822.         UnionRgn(gTempRgn, thePixels, thePixels);
  823.  
  824.         prevstripRect := stripRect;
  825.         startOfStrip := 0;
  826.         END;
  827.  
  828.     BEGIN
  829.     SetEmptyRgn(thePixels);
  830.  
  831.     IF NOT EmptyRgn(theCells) & Focus THEN
  832.         IF theCells^^.rgnSize = 10 THEN                 { the region is a rectangle }
  833.             BEGIN
  834.             cellBounds := theCells^^.rgnBBox;
  835.             SetVRect(pixels, fColWidths.SumValues(1, cellBounds.left - 1), fRowHeights.SumValues(1,
  836.                      cellBounds.top - 1), fColWidths.SumValues(1, cellBounds.right - 1),
  837.                      fRowHeights.SumValues(1, cellBounds.bottom - 1));
  838.             ViewToQDRect(pixels, thePixels^^.rgnBBox);
  839.             END
  840.         ELSE
  841.             BEGIN
  842.             { Reduce the cells to only those that are visible }
  843.             GetVisibleRect(visibleRect);
  844.             QDToViewRect(visibleRect, visibleVRect);
  845.             visibleCells.topLeft := VPointToLastCell(visibleVRect.topLeft);
  846.             visibleCells.botRight := VPointToLastCell(visibleVRect.botRight);
  847.             WITH visibleCells DO
  848.                 SetRectRgn(pVisibleCells, left, top, right + 1, bottom + 1);
  849.             SectRgn(theCells, pVisibleCells, pVisibleCells);
  850.             cellBounds := pVisibleCells^^.rgnBBox;
  851.  
  852.             {$IFC qDebug}
  853.             UseTempRgn('TGridView.CellsToPixels');
  854.             {$ENDC}
  855.             SetEmptyRgn(gTempRgn);
  856.             prevstripRect := gZeroRect;
  857.             direction := LongerSide(cellBounds);
  858.             IF direction = v THEN
  859.                 FOR col := cellBounds.left TO cellBounds.right - 1 DO
  860.                     BEGIN
  861.                     aCell.h := col;
  862.                     startOfStrip := 0;
  863.                     FOR row := cellBounds.top TO cellBounds.bottom - 1 DO
  864.                         BEGIN
  865.                         aCell.v := row;
  866.                         IF PtInRgn(aCell, pVisibleCells) THEN
  867.                             BEGIN
  868.                             IF startOfStrip = 0 THEN
  869.                                 startOfStrip := row
  870.                             END
  871.                         ELSE IF startOfStrip > 0 THEN
  872.                             AddStrip(row - 1);
  873.                         END;
  874.                     IF startOfStrip > 0 THEN
  875.                         AddStrip(cellBounds.bottom - 1);
  876.                     END
  877.             ELSE
  878.                 FOR row := cellBounds.top TO cellBounds.bottom - 1 DO
  879.                     BEGIN
  880.                     aCell.v := row;
  881.                     startOfStrip := 0;
  882.                     FOR col := cellBounds.left TO cellBounds.right - 1 DO
  883.                         BEGIN
  884.                         aCell.h := col;
  885.                         IF PtInRgn(aCell, pVisibleCells) THEN
  886.                             BEGIN
  887.                             IF startOfStrip = 0 THEN
  888.                                 startOfStrip := col
  889.                             END
  890.                         ELSE IF startOfStrip > 0 THEN
  891.                             AddStrip(col - 1);
  892.                         END;
  893.                     IF startOfStrip > 0 THEN
  894.                         AddStrip(cellBounds.right - 1);
  895.                     END;
  896.             {$IFC qDebug}
  897.             DoneWithTempRgn;
  898.             {$ENDC}
  899.             END;
  900.     END;
  901.  
  902. {--------------------------------------------------------------------------------------------------}
  903. {$S GVRes}
  904.  
  905. PROCEDURE TGridView.DoHighlightSelection(fromHL, toHL: HLState); OVERRIDE;
  906.  
  907.     BEGIN
  908.     IF NOT EmptyRgn(fHLRegion) THEN
  909.         HighlightCells(fHLRegion, fromHL, toHL)
  910.     END;
  911.  
  912. {--------------------------------------------------------------------------------------------------}
  913. {$S GVRes}
  914.  
  915. PROCEDURE TGridView.HighlightCells(theCells: RgnHandle;
  916.                                    fromHL, toHL: HLState);
  917.  
  918.     BEGIN
  919.     IF fromHL = hlDim THEN                                { GridViews don't support dim highlighting }
  920.         fromHL := hlOFF;
  921.     IF toHL = hlDim THEN
  922.         toHL := hlOFF;
  923.  
  924.     IF (fromHL <> toHL) & Focus THEN
  925.         BEGIN
  926.         CellsToPixels(theCells, pPixelsToHighlight);
  927.  
  928.         PenNormal;
  929.         UseSelectionColor;
  930.         InvertRgn(pPixelsToHighlight);                    { highlight the cells }
  931.         END;
  932.     END;
  933.  
  934. {--------------------------------------------------------------------------------------------------}
  935. {$S GVRes}
  936.  
  937. FUNCTION TGridView.DoMouseCommand(VAR theMouse: Point;
  938.                                   VAR info: EventInfo;
  939.                                   VAR hysteresis: Point): TCommand; OVERRIDE;
  940.  
  941.     VAR
  942.         aRow, aCol:         INTEGER;
  943.         aCellSelectCommand: TCellSelectCommand;
  944.  
  945.     BEGIN
  946.     DoMouseCommand := NIL;
  947.  
  948.     IF IdentifyPoint(theMouse, aRow, aCol) <> badChoice THEN
  949.         BEGIN
  950.         New(aCellSelectCommand);
  951.         FailNIL(aCellSelectCommand);
  952.         aCellSelectCommand.ICellSelectCommand(SELF, info.theShiftKey, info.theCmdKey);
  953.         DoMouseCommand := aCellSelectCommand;
  954.         END;
  955.     END;
  956.  
  957. {--------------------------------------------------------------------------------------------------}
  958. {$S GVRes}
  959.  
  960. PROCEDURE TGridView.Draw(area: Rect); OVERRIDE;
  961.  
  962.     VAR
  963.         aRect:                VRect;
  964.         bRect:                VRect;
  965.         aQDRect:            Rect;
  966.         i:                    INTEGER;
  967.         startCell:            GridCell;
  968.         stopCell:            GridCell;
  969.         viewArea:            VRect;
  970.         colWidth:            INTEGER;
  971.         rowHeight:            INTEGER;
  972.         constantWidth, constantHeight: BOOLEAN;
  973.         startCellToDraw:    GridCell;
  974.         cellsArea:            Rect;
  975.  
  976.     BEGIN
  977.     IF (fNumOfRows > 0) & (fNumOfCols > 0) THEN
  978.         BEGIN                                            { make sure we have something to draw }
  979.         QDToViewRect(area, viewArea);
  980.  
  981.         WITH viewArea DO
  982.             BEGIN
  983.             startCell := VPointToLastCell(topLeft);
  984.             stopCell := VPointToLastCell(botRight);
  985.             END;
  986.  
  987.         CellToVRect(startCell, aRect);
  988.         CellToVRect(stopCell, bRect);
  989.         bRect.topLeft := aRect.topLeft;
  990.         ViewToQDRect(bRect, area);
  991.  
  992.         startCellToDraw := startCell;
  993.         cellsArea := area;
  994.         IF viewArea.top >= aRect.bottom - BSR(fRowInset, 1) THEN
  995.             BEGIN
  996.             startCellToDraw.v := startCellToDraw.v + 1;
  997.             cellsArea.top := cellsArea.top - aRect.top + aRect.bottom;
  998.             END;
  999.  
  1000.         DrawRangeOfCells(startCellToDraw, stopCell, cellsArea);
  1001.  
  1002.         IF fAdornCols THEN
  1003.             BEGIN
  1004.             aQDRect := area;
  1005.  
  1006.             constantWidth := fColWidths.fNoOfChunks = 1;
  1007.             IF constantWidth THEN                        { only one width }
  1008.                 colWidth := GetColWidth(1);
  1009.  
  1010.             FOR i := startCell.h TO stopCell.h DO
  1011.                 BEGIN
  1012.                 IF constantWidth THEN
  1013.                     aQDRect.right := aQDRect.left + colWidth
  1014.                 ELSE
  1015.                     aQDRect.right := aQDRect.left + GetColWidth(i);
  1016.  
  1017.                 AdornCol(i, aQDRect);
  1018.                 aQDRect.left := aQDRect.right;
  1019.                 END;
  1020.             END;
  1021.  
  1022.         IF fAdornRows THEN
  1023.             BEGIN
  1024.             aQDRect := area;
  1025.  
  1026.             constantHeight := fRowHeights.fNoOfChunks = 1;
  1027.             IF constantHeight THEN                        { only one height }
  1028.                 rowHeight := GetRowHeight(1);
  1029.  
  1030.             FOR i := startCell.v TO stopCell.v DO
  1031.                 BEGIN
  1032.                 IF constantHeight THEN
  1033.                     aQDRect.bottom := aQDRect.top + rowHeight
  1034.                 ELSE
  1035.                     aQDRect.bottom := aQDRect.top + GetRowHeight(i);
  1036.  
  1037.                 AdornRow(i, aQDRect);
  1038.                 aQDRect.top := aQDRect.bottom;
  1039.                 END;
  1040.             END;
  1041.         END;
  1042.  
  1043.     INHERITED Draw(area);
  1044.     END;
  1045.  
  1046. {--------------------------------------------------------------------------------------------------}
  1047. {$S GVRes}
  1048.  
  1049. PROCEDURE TGridView.DrawRangeOfCells(startCell, stopCell: GridCell;
  1050.                                      aQDRect: Rect);
  1051.  
  1052.     VAR
  1053.         colWidth:            INTEGER;
  1054.         rowHeight:            INTEGER;
  1055.         i, j:                INTEGER;
  1056.         aCell:                GridCell;
  1057.         left:                INTEGER;
  1058.  
  1059.     BEGIN
  1060.  
  1061.     aQDRect.left := aQDRect.left + BSR(fColInset, 1);    { fColInset DIV 2 }
  1062.     aQDRect.top := aQDRect.top + BSR(fRowInset, 1);     { fRowInset DIV 2 }
  1063.     left := aQDRect.left;
  1064.  
  1065.     IF fColWidths.fNoOfChunks = 1 THEN                    { only one width }
  1066.         colWidth := GetColWidth(1);
  1067.     IF fRowHeights.fNoOfChunks = 1 THEN                 { only one height }
  1068.         rowHeight := GetRowHeight(1);
  1069.  
  1070.     FOR j := startCell.v TO stopCell.v DO
  1071.         BEGIN
  1072.         IF fRowHeights.fNoOfChunks = 1 THEN             { only one height }
  1073.             aQDRect.bottom := aQDRect.top + rowHeight - fRowInset
  1074.         ELSE
  1075.             aQDRect.bottom := aQDRect.top + GetRowHeight(j) - fRowInset;
  1076.  
  1077.         aQDRect.left := left;                            { start back at the left for the next row }
  1078.  
  1079.         FOR i := startCell.h TO stopCell.h DO
  1080.             BEGIN
  1081.             IF fColWidths.fNoOfChunks = 1 THEN            { only one height }
  1082.                 aQDRect.right := aQDRect.left + colWidth - fColInset
  1083.             ELSE
  1084.                 aQDRect.right := aQDRect.left + GetColWidth(i) - fColInset;
  1085.  
  1086.             aCell.h := i;
  1087.             aCell.v := j;
  1088.             DrawCell(aCell, aQDRect);
  1089.  
  1090.             aQDRect.left := aQDRect.right + fColInset;
  1091.             END;
  1092.         aQDRect.top := aQDRect.bottom + fRowInset;
  1093.         END;
  1094.     END;
  1095.  
  1096. {--------------------------------------------------------------------------------------------------}
  1097. {$S GVRes}
  1098.  
  1099. PROCEDURE TGridView.DrawCell(aCell: GridCell;
  1100.                              aQDRect: Rect);
  1101.  
  1102.     BEGIN
  1103.     { Should always be overridden.}
  1104.  
  1105.     {$IFC qDebug}
  1106.     Writeln('TGridView: DrawCell MUST be overridden!');
  1107.     {$ENDC qDebug}
  1108.     END;
  1109.  
  1110. {--------------------------------------------------------------------------------------------------}
  1111. {$S GVNonRes}
  1112.  
  1113. PROCEDURE TGridView.DelColAt(aCol: INTEGER;
  1114.                              numOfCols: INTEGER);
  1115.  
  1116.     VAR
  1117.         aRect:                VRect;
  1118.  
  1119.     BEGIN
  1120.     IF (aCol < 1) | (numOfCols < 1) | (aCol + numOfCols - 1 > fNumOfCols) THEN
  1121.         BEGIN
  1122.         IF numOfCols <> 0 THEN
  1123.             BEGIN
  1124.             {$IFC qDebug AND qRangeCheck}
  1125.             Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1126.             ProgramBreak('Range Check in DelColAt');
  1127.             EXIT(DelColAt);
  1128.             {$ENDC}
  1129.             END;
  1130.         END
  1131.     ELSE
  1132.         BEGIN
  1133.         ColToVRect(Max(1, aCol), Max(1, fNumOfCols - aCol + 1), aRect);
  1134.         fColWidths.DeleteItems(aCol, numOfCols);
  1135.         fNumOfCols := fNumOfCols - numOfCols;
  1136.         AdjustSize;
  1137.         InvalidVRect(aRect);
  1138.         END;
  1139.     END;
  1140.  
  1141. {--------------------------------------------------------------------------------------------------}
  1142. {$S GVNonRes}
  1143.  
  1144. PROCEDURE TGridView.DelRowAt(aRow: INTEGER;
  1145.                              numOfRows: INTEGER);
  1146.  
  1147.     VAR
  1148.         aRect:                VRect;
  1149.  
  1150.     BEGIN
  1151.     IF (aRow < 1) | (numOfRows < 1) | (aRow + numOfRows - 1 > fNumOfRows) THEN
  1152.         BEGIN
  1153.         IF numOfRows <> 0 THEN
  1154.             BEGIN
  1155.             {$IFC qDebug AND qRangeCheck}
  1156.             Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1157.             ProgramBreak('Range Check in DelRowAt');
  1158.             EXIT(DelRowAt);
  1159.             {$ENDC}
  1160.             END;
  1161.         END
  1162.     ELSE
  1163.         BEGIN
  1164.         RowToVRect(Max(1, aRow), Max(1, fNumOfRows - aRow + 1), aRect);
  1165.         fRowHeights.DeleteItems(aRow, numOfRows);
  1166.         fNumOfRows := fNumOfRows - numOfRows;
  1167.         AdjustSize;
  1168.         InvalidVRect(aRect);
  1169.         END;
  1170.     END;
  1171.  
  1172. {--------------------------------------------------------------------------------------------------}
  1173. {$S GVNonRes}
  1174.  
  1175. PROCEDURE TGridView.DelColFirst(numOfCols: INTEGER);
  1176.  
  1177.     BEGIN
  1178.     DelColAt(1, numOfCols);
  1179.     END;
  1180.  
  1181. {--------------------------------------------------------------------------------------------------}
  1182. {$S GVNonRes}
  1183.  
  1184. PROCEDURE TGridView.DelRowFirst(numOfRows: INTEGER);
  1185.  
  1186.     BEGIN
  1187.     DelRowAt(1, numOfRows);
  1188.     END;
  1189.  
  1190. {--------------------------------------------------------------------------------------------------}
  1191. {$S GVNonRes}
  1192.  
  1193. PROCEDURE TGridView.DelColLast(numOfCols: INTEGER);
  1194.  
  1195.     BEGIN
  1196.     DelColAt(fNumOfCols - numOfCols + 1, numOfCols);
  1197.     END;
  1198.  
  1199. {--------------------------------------------------------------------------------------------------}
  1200. {$S GVNonRes}
  1201.  
  1202. PROCEDURE TGridView.DelRowLast(numOfRows: INTEGER);
  1203.  
  1204.     BEGIN
  1205.     DelRowAt(fNumOfRows - numOfRows + 1, numOfRows);
  1206.     END;
  1207.  
  1208. {--------------------------------------------------------------------------------------------------}
  1209. {$S GVRes}
  1210.  
  1211. PROCEDURE TGridView.EachCellDo(startCell, stopCell: GridCell;
  1212.                                PROCEDURE DoToCell(aCell: GridCell));
  1213.  
  1214.     VAR
  1215.         i, j:                INTEGER;
  1216.         firstRow:            INTEGER;
  1217.         lastRow:            INTEGER;
  1218.         firstCol:            INTEGER;
  1219.         lastCol:            INTEGER;
  1220.         aCell:                GridCell;
  1221.  
  1222.     BEGIN
  1223.     firstRow := Max(1, startCell.v);
  1224.     firstCol := Max(1, startCell.h);
  1225.     lastRow := Min(fNumOfRows, stopCell.v);
  1226.     lastCol := Min(fNumOfCols, stopCell.h);
  1227.  
  1228.     FOR j := firstRow TO lastRow DO
  1229.         BEGIN
  1230.         aCell.v := j;
  1231.         FOR i := firstCol TO lastCol DO
  1232.             BEGIN
  1233.             aCell.h := i;
  1234.             DoToCell(aCell);
  1235.             END;
  1236.         END;
  1237.     END;
  1238.  
  1239. {--------------------------------------------------------------------------------------------------}
  1240. {$S GVRes}
  1241.  
  1242. PROCEDURE TGridView.EachSelectedCellDo(PROCEDURE DoToCell(aCell: GridCell));
  1243.  
  1244.     BEGIN
  1245.     EachInRgn(fSelections, DoToCell);
  1246.     END;
  1247.  
  1248. {--------------------------------------------------------------------------------------------------}
  1249. {$S GVRes}
  1250.  
  1251. PROCEDURE TGridView.EachInRgn(aRgn: RgnHandle;
  1252.                               PROCEDURE DoToCell(aCell: GridCell));
  1253.  
  1254.     VAR
  1255.         row, col:            INTEGER;
  1256.         aCell:                GridCell;
  1257.         boundRect:            Rect;
  1258.  
  1259.     BEGIN
  1260.     boundRect := aRgn^^.rgnBBox;
  1261.     boundRect.right := boundRect.right - 1;
  1262.     boundRect.bottom := boundRect.bottom - 1;
  1263.     IF aRgn^^.rgnSize = 10 THEN                         { its a rectangle}
  1264.         EachCellDo(boundRect.topLeft, boundRect.botRight, DoToCell)
  1265.     ELSE
  1266.         FOR row := boundRect.top TO boundRect.bottom DO
  1267.             BEGIN
  1268.             aCell.v := row;
  1269.             FOR col := boundRect.left TO boundRect.right DO
  1270.                 BEGIN
  1271.                 aCell.h := col;
  1272.                 IF PtInRgn(aCell, aRgn) THEN
  1273.                     DoToCell(aCell);
  1274.                 END;
  1275.             END;
  1276.     END;
  1277.  
  1278. {--------------------------------------------------------------------------------------------------}
  1279. {$S GVRes}
  1280.  
  1281. FUNCTION TGridView.FirstSelectedCell: GridCell;
  1282.  
  1283.     VAR
  1284.         i, j:                INTEGER;
  1285.         bounds:             Rect;
  1286.         aCell:                GridCell;
  1287.  
  1288.     BEGIN
  1289.     IF EmptyRgn(fSelections) THEN
  1290.         FirstSelectedCell := gZeroPt
  1291.     ELSE
  1292.         BEGIN
  1293.         bounds := fSelections^^.rgnBBox;
  1294.         IF fSelections^^.rgnSize = 10 THEN                { whole rectangle }
  1295.             FirstSelectedCell := bounds.topLeft
  1296.         ELSE
  1297.             FOR i := bounds.top TO bounds.bottom - 1 DO
  1298.                 BEGIN
  1299.                 aCell.v := i;
  1300.                 FOR j := bounds.left TO bounds.right - 1 DO
  1301.                     BEGIN
  1302.                     aCell.h := j;
  1303.                     IF PtInRgn(aCell, fSelections) THEN
  1304.                         BEGIN
  1305.                         FirstSelectedCell := aCell;
  1306.                         EXIT(FirstSelectedCell);
  1307.                         END;
  1308.                     END;
  1309.                 END
  1310.         END;
  1311.     END;
  1312.  
  1313. {--------------------------------------------------------------------------------------------------}
  1314. {$S GVRes}
  1315.  
  1316. FUNCTION TGridView.GetColWidth(aCol: INTEGER): INTEGER;
  1317.  
  1318.     BEGIN
  1319.     IF (aCol < 1) | (aCol > fNumOfCols) THEN
  1320.         BEGIN
  1321.         {$IFC qRangeCheck AND qDebug}
  1322.         Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1323.         ProgramBreak('Range Check in GetColWidth');
  1324.         {$ENDC}
  1325.         GetColWidth := 0;
  1326.         END
  1327.     ELSE
  1328.         GetColWidth := fColWidths.GetValue(aCol);
  1329.     END;
  1330.  
  1331. {--------------------------------------------------------------------------------------------------}
  1332. {$S GVRes}
  1333.  
  1334. FUNCTION TGridView.GetRowHeight(aRow: INTEGER): INTEGER;
  1335.  
  1336.     BEGIN
  1337.     IF (aRow < 1) | (aRow > fNumOfRows) THEN
  1338.         BEGIN
  1339.         {$IFC qRangeCheck AND qDebug}
  1340.         Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1341.         ProgramBreak('Range Check in GetRowHeight');
  1342.         {$ENDC}
  1343.         GetRowHeight := 0;
  1344.         END
  1345.     ELSE
  1346.         GetRowHeight := fRowHeights.GetValue(aRow);
  1347.     END;
  1348.  
  1349. {--------------------------------------------------------------------------------------------------}
  1350. {$S GVRes}
  1351.  
  1352. PROCEDURE TGridView.InvalidateCell(aCell: GridCell);
  1353.  
  1354.     VAR
  1355.         aRect:                VRect;
  1356.  
  1357.     BEGIN
  1358.     CellToVRect(aCell, aRect);
  1359.     InvalidVRect(aRect);
  1360.     END;
  1361.  
  1362. {--------------------------------------------------------------------------------------------------}
  1363. {$S GVRes}
  1364.  
  1365. PROCEDURE TGridView.InvalidateSelection;
  1366.  
  1367.     BEGIN
  1368.     IF Focus THEN
  1369.         BEGIN
  1370.         CellsToPixels(fSelections, pInvalidateRgn);
  1371.         SectRgn(pInvalidateRgn, thePort^.clipRgn, pInvalidateRgn);
  1372.         InvalRgn(pInvalidateRgn);
  1373.         END;
  1374.     END;
  1375.  
  1376. {--------------------------------------------------------------------------------------------------}
  1377. {$S GVRes}
  1378.  
  1379. FUNCTION TGridView.IdentifyPoint(theQDPoint: Point;
  1380.                                  VAR aRow, aCol: INTEGER): GridViewPart;
  1381.  
  1382.     VAR
  1383.         aRect:                VRect;
  1384.         aPoint:             VPoint;
  1385.         aCell:                GridCell;
  1386.         aGridViewPart:        GridViewPart;
  1387.  
  1388.     BEGIN
  1389.     QDToViewPt(theQDPoint, aPoint);
  1390.     aCell := VPointToCell(aPoint);
  1391.     aRow := aCell.v;
  1392.     aCol := aCell.h;
  1393.  
  1394.     IF LONGINT(aCell) = 0 THEN
  1395.         aGridViewPart := badChoice
  1396.     ELSE
  1397.         BEGIN
  1398.         CellToVRect(aCell, aRect);
  1399.         InsetVRect(aRect, fColInset DIV 2, fRowInset DIV 2);
  1400.         aGridViewPart := inCell;
  1401.  
  1402.         IF fColInset > 0 THEN
  1403.             BEGIN
  1404.             IF (aPoint.h < aRect.left) THEN
  1405.                 BEGIN
  1406.                 aGridViewPart := inColumn;                { To the left of the cell }
  1407.                 END
  1408.  
  1409.             ELSE IF (aPoint.h >= aRect.right) THEN        { Remember PtInRgn will report a point as in
  1410.                                                          a region only if the pixel to the right
  1411.                                                          and below the point is contained in the
  1412.                                                          region. }
  1413.                 BEGIN
  1414.                 aGridViewPart := inColumn;                { To the right of the cell }
  1415.                 aCol := aCol + 1;
  1416.                 END;
  1417.             END;
  1418.  
  1419.         IF fRowInset > 0 THEN
  1420.             BEGIN
  1421.             IF (aPoint.v < aRect.top) THEN
  1422.                 BEGIN
  1423.                 IF (aGridViewPart = inColumn) THEN
  1424.                     aGridViewPart := inVertex            { Click on both }
  1425.                 ELSE
  1426.                     aGridViewPart := inRow;             { Above the cell }
  1427.                 END
  1428.  
  1429.             ELSE IF (aPoint.v >= aRect.bottom) THEN     { Remember PtInRgn will report a point as in
  1430.                                                          a region only if the pixel to the right
  1431.                                                          and below the point is contained in the
  1432.                                                          region. }
  1433.                 BEGIN
  1434.                 IF (aGridViewPart = inColumn) THEN
  1435.                     aGridViewPart := inVertex            { Click on both }
  1436.                 ELSE
  1437.                     aGridViewPart := inRow;             { Above the cell }
  1438.                 aRow := aRow + 1;
  1439.                 END;
  1440.             END;
  1441.         END;
  1442.     IdentifyPoint := aGridViewPart;
  1443.     END;
  1444.  
  1445. {--------------------------------------------------------------------------------------------------}
  1446. {$S GVRes}
  1447.  
  1448. PROCEDURE TGridView.InsColBefore(aCol: INTEGER;
  1449.                                  numOfCols: INTEGER;
  1450.                                  aWidth: INTEGER);
  1451.  
  1452.     VAR
  1453.         aRect:                VRect;
  1454.  
  1455.     BEGIN
  1456.     IF (aCol < 1) | (numOfCols < 1) THEN
  1457.         BEGIN
  1458.         IF numOfCols <> 0 THEN
  1459.             BEGIN
  1460.             {$IFC qDebug AND qRangeCheck}
  1461.             Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1462.             ProgramBreak('Range Check in InsColBefore');
  1463.             {$ENDC}
  1464.             END;
  1465.         END
  1466.     ELSE
  1467.         BEGIN
  1468.         fColWidths.InsertItems(aCol, numOfCols, aWidth);
  1469.         fNumOfCols := fNumOfCols + numOfCols;
  1470.         AdjustSize;
  1471.         ColToVRect(Max(1, aCol), Max(1, fNumOfCols - aCol + 1), aRect);
  1472.         InvalidVRect(aRect);
  1473.         END;
  1474.     END;
  1475.  
  1476. {--------------------------------------------------------------------------------------------------}
  1477. {$S GVRes}
  1478.  
  1479. PROCEDURE TGridView.InsRowBefore(aRow: INTEGER;
  1480.                                  numOfRows: INTEGER;
  1481.                                  aHeight: INTEGER);
  1482.  
  1483.     VAR
  1484.         aRect:                VRect;
  1485.  
  1486.     BEGIN
  1487.     IF (aRow < 1) | (numOfRows < 1) THEN
  1488.         BEGIN
  1489.         IF numOfRows <> 0 THEN
  1490.             BEGIN
  1491.             {$IFC qDebug AND qRangeCheck}
  1492.             Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1493.             ProgramBreak('Range Check in InsRowBefore');
  1494.             {$ENDC}
  1495.             END;
  1496.         END
  1497.     ELSE
  1498.         BEGIN
  1499.         fRowHeights.InsertItems(aRow, numOfRows, aHeight);
  1500.         fNumOfRows := fNumOfRows + numOfRows;
  1501.         AdjustSize;
  1502.         RowToVRect(Max(1, aRow), Max(1, fNumOfRows - aRow + 1), aRect);
  1503.         InvalidVRect(aRect);
  1504.         END;
  1505.     END;
  1506.  
  1507. {--------------------------------------------------------------------------------------------------}
  1508. {$S GVRes}
  1509.  
  1510. PROCEDURE TGridView.InsColLast(numOfCols: INTEGER;
  1511.                                aWidth: INTEGER);
  1512.  
  1513.     BEGIN
  1514.     InsColBefore(fNumOfCols + 1, numOfCols, aWidth);
  1515.     END;
  1516.  
  1517. {--------------------------------------------------------------------------------------------------}
  1518. {$S GVRes}
  1519.  
  1520. PROCEDURE TGridView.InsRowLast(numOfRows: INTEGER;
  1521.                                aHeight: INTEGER);
  1522.  
  1523.     BEGIN
  1524.     InsRowBefore(fNumOfRows + 1, numOfRows, aHeight);
  1525.     END;
  1526.  
  1527. {--------------------------------------------------------------------------------------------------}
  1528. {$S GVRes}
  1529.  
  1530. PROCEDURE TGridView.InsColFirst(numOfCols: INTEGER;
  1531.                                 aWidth: INTEGER);
  1532.  
  1533.     BEGIN
  1534.     InsColBefore(1, numOfCols, aWidth);
  1535.     END;
  1536.  
  1537. {--------------------------------------------------------------------------------------------------}
  1538. {$S GVRes}
  1539.  
  1540. PROCEDURE TGridView.InsRowFirst(numOfRows: INTEGER;
  1541.                                 aHeight: INTEGER);
  1542.  
  1543.     BEGIN
  1544.     InsRowBefore(1, numOfRows, aHeight);
  1545.     END;
  1546.  
  1547. {--------------------------------------------------------------------------------------------------}
  1548. {$S GVRes}
  1549.  
  1550. FUNCTION TGridView.IsCellSelected(aCell: GridCell): BOOLEAN;
  1551.  
  1552.     BEGIN
  1553.     IsCellSelected := PtInRgn(aCell, fSelections);
  1554.     END;
  1555.  
  1556. {--------------------------------------------------------------------------------------------------}
  1557. {$S GVRes}
  1558.  
  1559. FUNCTION TGridView.LastSelectedCell: GridCell;
  1560.  
  1561.     VAR
  1562.         i, j:                INTEGER;
  1563.         bounds:             Rect;
  1564.         aCell:                GridCell;
  1565.  
  1566.     BEGIN
  1567.     LastSelectedCell := gZeroPt;
  1568.     IF NOT EmptyRgn(fSelections) THEN
  1569.         BEGIN
  1570.         bounds := fSelections^^.rgnBBox;
  1571.         IF fSelections^^.rgnSize = 10 THEN                { whole rectangle }
  1572.             BEGIN
  1573.             aCell.h := bounds.right - 1;
  1574.             aCell.v := bounds.bottom - 1;
  1575.             LastSelectedCell := aCell;
  1576.             END
  1577.         ELSE
  1578.             FOR i := bounds.bottom - 1 DOWNTO bounds.top DO
  1579.                 BEGIN
  1580.                 aCell.v := i;
  1581.                 FOR j := bounds.right - 1 DOWNTO bounds.left DO
  1582.                     BEGIN
  1583.                     aCell.h := j;
  1584.                     IF PtInRgn(aCell, fSelections) THEN
  1585.                         BEGIN
  1586.                         LastSelectedCell := aCell;
  1587.                         EXIT(LastSelectedCell);
  1588.                         END;
  1589.                     END;
  1590.                 END
  1591.         END;
  1592.     END;
  1593.  
  1594. {--------------------------------------------------------------------------------------------------}
  1595. {$S GVRes}
  1596.  
  1597. PROCEDURE TGridView.RowToVRect(aRow: INTEGER;
  1598.                                numOfRows: INTEGER;
  1599.                                VAR aRect: VRect);
  1600.  
  1601.     VAR
  1602.         height:             LONGINT;
  1603.         topEdge:            LONGINT;
  1604.  
  1605.     BEGIN
  1606.     IF (aRow < 1) | (numOfRows < 1) | (aRow + numOfRows - 1 > fNumOfRows) THEN
  1607.         BEGIN
  1608.         {$IFC qDebug AND qRangeCheck}
  1609.         Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1610.         ProgramBreak('Range Check in RowToVRect');
  1611.         {$ENDC}
  1612.         SetVRect(aRect, 0, 0, 0, 0);
  1613.         END
  1614.     ELSE                                                { all the params look OK }
  1615.         BEGIN
  1616.         IF fRowHeights.fNoOfChunks = 1 THEN             { only one row height }
  1617.             BEGIN
  1618.             height := fRowHeights.GetValue(1);
  1619.             topEdge := IntMultiply(height, aRow - 1);
  1620.             height := IntMultiply(height, numOfRows);
  1621.             END
  1622.         ELSE
  1623.             BEGIN
  1624.             topEdge := fRowHeights.SumValues(1, aRow - 1);
  1625.             height := fRowHeights.SumValues(aRow, numOfRows);
  1626.             END;
  1627.  
  1628.         SetVRect(aRect, 0, topEdge, fColWidths.fTotal, topEdge + height);
  1629.         END;
  1630.     END;
  1631.  
  1632. {--------------------------------------------------------------------------------------------------}
  1633. {$S GVRes}
  1634.  
  1635. PROCEDURE TGridView.ScrollSelectionIntoView(redraw: BOOLEAN);
  1636.  
  1637.     VAR
  1638.         botRightCell:        GridCell;
  1639.         topLeftRect, botRightRect, selectionRect: VRect;
  1640.         minToSee:            Point;
  1641.  
  1642.     BEGIN
  1643.     IF NOT (EmptyRgn(fSelections)) THEN
  1644.         BEGIN
  1645.         CellToVRect(fSelections^^.rgnBBox.topLeft, topLeftRect);
  1646.         SetPt(botRightCell, fSelections^^.rgnBBox.right - 1, fSelections^^.rgnBBox.bottom - 1);
  1647.         CellToVRect(botRightCell, botRightRect);
  1648.         UnionVRect(topLeftRect, botRightRect, selectionRect);
  1649.         minToSee.v := Max(topLeftRect.bottom - topLeftRect.top, botRightRect.bottom -
  1650.                           botRightRect.top);
  1651.         minToSee.h := Max(topLeftRect.right - topLeftRect.left, botRightRect.right -
  1652.                           botRightRect.left);
  1653.         RevealRect(selectionRect, minToSee, redraw);
  1654.         END;
  1655.     END;
  1656.  
  1657. {--------------------------------------------------------------------------------------------------}
  1658. {$S GVNonRes}
  1659.  
  1660. PROCEDURE TGridView.SetColWidth(aCol: INTEGER;
  1661.                                 numOfCols: INTEGER;
  1662.                                 aWidth: INTEGER);
  1663.  
  1664.     VAR
  1665.         aRect:                VRect;
  1666.  
  1667.     BEGIN
  1668.     {$IFC qRangeCheck AND qDebug}
  1669.     IF (aCol < 1) | (numOfCols < 1) | (aCol + numOfCols - 1 > fNumOfCols) THEN
  1670.         BEGIN
  1671.         Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1672.         ProgramBreak('Range Check in SetColWidth');
  1673.         EXIT(SetColWidth);
  1674.         END;
  1675.     {$ENDC}
  1676.  
  1677.     IF (fColWidths.fNoOfChunks > 1) | (GetColWidth(1) <> aWidth) THEN
  1678.         BEGIN
  1679.         fColWidths.DeleteItems(aCol, numOfCols);
  1680.         fColWidths.InsertItems(aCol, numOfCols, aWidth);
  1681.         AdjustSize;
  1682.         ColToVRect(Max(1, aCol), Max(1, fNumOfCols - aCol + 1), aRect);
  1683.         InvalidVRect(aRect);
  1684.         END;
  1685.     END;
  1686.  
  1687. {--------------------------------------------------------------------------------------------------}
  1688. {$S GVNonRes}
  1689.  
  1690. PROCEDURE TGridView.SetRowHeight(aRow: INTEGER;
  1691.                                  numOfRows: INTEGER;
  1692.                                  aHeight: INTEGER);
  1693.  
  1694.     VAR
  1695.         aRect:                VRect;
  1696.  
  1697.     BEGIN
  1698.     {$IFC qRangeCheck AND qDebug}
  1699.     IF (aRow < 1) | (numOfRows < 1) | (aRow + numOfRows - 1 > fNumOfRows) THEN
  1700.         BEGIN
  1701.         Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1702.         ProgramBreak('Range Check in SetRowHeight');
  1703.         EXIT(SetRowHeight);
  1704.         END;
  1705.     {$ENDC}
  1706.  
  1707.     IF NOT ((fRowHeights.fNoOfChunks = 1) & (GetRowHeight(1) = aHeight)) THEN
  1708.         BEGIN
  1709.         fRowHeights.DeleteItems(aRow, numOfRows);
  1710.         fRowHeights.InsertItems(aRow, numOfRows, aHeight);
  1711.         AdjustSize;
  1712.         RowToVRect(Max(1, aRow), Max(1, fNumOfRows - aRow + 1), aRect);
  1713.         InvalidVRect(aRect);
  1714.         END;
  1715.     END;
  1716.  
  1717. {--------------------------------------------------------------------------------------------------}
  1718. {$S GVRes}
  1719.  
  1720. PROCEDURE TGridView.SelectCell(theCell: GridCell;
  1721.                                extendSelection, highlight, select: BOOLEAN);
  1722.  
  1723.     BEGIN
  1724.     WITH theCell DO
  1725.         SetSelectionRect(h, v, h, v, extendSelection, highlight, select);
  1726.     END;
  1727.  
  1728. {--------------------------------------------------------------------------------------------------}
  1729. {$S GVRes}
  1730.  
  1731. PROCEDURE TGridView.SetEmptySelection(highlight: BOOLEAN);
  1732.  
  1733.     BEGIN
  1734.     SetEmptyRgn(fTempSelections);
  1735.     SetSelection(fTempSelections, kDontExtend, highlight, kSelect);
  1736.     END;
  1737.  
  1738. {--------------------------------------------------------------------------------------------------}
  1739. {$S GVRes}
  1740.  
  1741. PROCEDURE TGridView.SetSelection(cellsToSelect: RgnHandle;
  1742.                                  extendSelection, highlight, select: BOOLEAN);
  1743.  
  1744.     BEGIN
  1745.     {$IFC qDebug}
  1746.     WITH cellsToSelect^^.rgnBBox DO
  1747.         IF fSingleSelection & ((right - left > 1) | (bottom - top > 1)) THEN
  1748.             ProgramBreak('Attempt to select multiple cells when fSingleSelection is true');
  1749.     IF NOT EmptyRgn(cellsToSelect) THEN
  1750.         WITH cellsToSelect^^.rgnBBox DO
  1751.             IF (left < 1) | (top < 1) | (right > fNumOfCols + 1) | (bottom > fNumOfRows + 1) THEN
  1752.                 ProgramBreak('Attempted selection is outside the range of cells');
  1753.     {$ENDC}
  1754.  
  1755.     IF highlight THEN
  1756.         CopyRgn(fSelections, pPreviousSelection);        { save the old selection }
  1757.  
  1758.     {$IFC qDebug}
  1759.     UseTempRgn('TGridView.SetSelection');
  1760.     {$ENDC}
  1761.     SetRectRgn(gTempRgn, 1, 1, fNumOfCols + 1, fNumOfRows + 1);
  1762.     SectRgn(cellsToSelect, gTempRgn, gTempRgn);
  1763.  
  1764.     IF extendSelection & select THEN                    { extend the selection region }
  1765.         UnionRgn(gTempRgn, fSelections, fSelections)
  1766.     ELSE IF select THEN                                 { reset the selection region }
  1767.         CopyRgn(gTempRgn, fSelections)
  1768.     ELSE                                                { need to de-select the new region }
  1769.         DiffRgn(fSelections, gTempRgn, fSelections);
  1770.     {$IFC qDebug}
  1771.     DoneWithTempRgn;
  1772.     {$ENDC}
  1773.  
  1774.     CopyRgn(fSelections, fHLRegion);
  1775.  
  1776.     IF highlight THEN
  1777.         BEGIN
  1778.         { Turn the deselected cells off }
  1779.         DiffRgn(pPreviousSelection, fSelections, pDifference);
  1780.         HighlightCells(pDifference, fHLDesired, hlOFF);
  1781.  
  1782.         { Turn the newly selected cells on }
  1783.         DiffRgn(fSelections, pPreviousSelection, pDifference);
  1784.         HighlightCells(pDifference, hlOFF, fHLDesired);
  1785.         END;
  1786.     END;
  1787.  
  1788. {--------------------------------------------------------------------------------------------------}
  1789. {$S GVRes}
  1790.  
  1791. PROCEDURE TGridView.SetSelectionRect(left, top, right, bottom: INTEGER;
  1792.                                      extendSelection, highlight, select: BOOLEAN);
  1793.  
  1794.     BEGIN
  1795.     IF (left = 0) & (top = 0) & (right = 0) & (bottom = 0) THEN
  1796.         SetEmptyRgn(fTempSelections)
  1797.     ELSE
  1798.         SetRectRgn(fTempSelections, left, top, right + 1, bottom + 1);
  1799.     SetSelection(fTempSelections, extendSelection, highlight, select);
  1800.     END;
  1801.  
  1802. {--------------------------------------------------------------------------------------------------}
  1803. {$S GVNonRes}
  1804.  
  1805. PROCEDURE TGridView.SetSingleSelection(theSetting: BOOLEAN);
  1806.  
  1807.     BEGIN
  1808.     fSingleSelection := theSetting;
  1809.     END;
  1810.  
  1811. {--------------------------------------------------------------------------------------------------}
  1812. {$S GVRes}
  1813.  
  1814. FUNCTION TGridView.VPointToCell(aPoint: VPoint): GridCell;
  1815.  
  1816.     VAR
  1817.         aCell:                GridCell;
  1818.  
  1819.     BEGIN
  1820.     aCell.h := fColWidths.FindItem(aPoint.h);
  1821.     aCell.v := fRowHeights.FindItem(aPoint.v);
  1822.     IF (aCell.h = 0) | (aCell.v = 0) THEN
  1823.         VPointToCell := gZeroPt
  1824.     ELSE
  1825.         VPointToCell := aCell;
  1826.     END;
  1827.  
  1828. {--------------------------------------------------------------------------------------------------}
  1829. {$S GVRes}
  1830.  
  1831. FUNCTION TGridView.VPointToLastCell(aPoint: VPoint): GridCell;
  1832.  
  1833.     VAR
  1834.         aCell:                GridCell;
  1835.  
  1836.     BEGIN
  1837.     aCell.h := fColWidths.FindItem(aPoint.h);
  1838.     IF aCell.h = 0 THEN                                 { If its invalid, return the last column }
  1839.         aCell.h := fNumOfCols;
  1840.  
  1841.     aCell.v := fRowHeights.FindItem(aPoint.v);
  1842.     IF aCell.v = 0 THEN                                 { If its invalid, return the last row }
  1843.         aCell.v := fNumOfRows;
  1844.  
  1845.     VPointToLastCell := aCell;
  1846.     END;
  1847.  
  1848. {--------------------------------------------------------------------------------------------------}
  1849. {$S GVFields}
  1850.  
  1851. PROCEDURE TGridView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1852.                                                fieldAddr: Ptr;
  1853.                                                fieldType: INTEGER)); OVERRIDE;
  1854.  
  1855.     BEGIN
  1856.     DoToField('TGridView', NIL, bClass);
  1857.     DoToField('fSelections', @fSelections, bRgnHandle);
  1858.     DoToField('fHLRegion', @fHLRegion, bRgnHandle);
  1859.     DoToField('fTempSelections', @fTempSelections, bRgnHandle);
  1860.     DoToField('fNumOfRows', @fNumOfRows, bInteger);
  1861.     DoToField('fRowHeights', @fRowHeights, bObject);
  1862.     DoToField('fNumOfCols', @fNumOfCols, bInteger);
  1863.     DoToField('fColWidths', @fColWidths, bObject);
  1864.     DoToField('fRowInset', @fRowInset, bInteger);
  1865.     DoToField('fColInset', @fColInset, bInteger);
  1866.     DoToField('fAdornRows', @fAdornRows, bBoolean);
  1867.     DoToField('fAdornCols', @fAdornCols, bBoolean);
  1868.     DoToField('fSingleSelection', @fSingleSelection, bBoolean);
  1869.  
  1870.     INHERITED Fields(DoToField);
  1871.     END;
  1872.  
  1873. {--------------------------------------------------------------------------------------------------}
  1874. {$S GVOpen}
  1875.  
  1876. PROCEDURE TTextGridView.ITextGridView(itsDocument: TDocument; { Its document }
  1877.                                       itsSuperView: TView; { Its parent view }
  1878.                                       itsLocation: VPoint; { Top, Left in parent's coords }
  1879.                                       itsSize: VPoint;
  1880.                                       itsHSizeDet, itsVSizeDet: SizeDeterminer; { Size determiners }
  1881.                                       numOfRows: INTEGER; { Number of rows initially }
  1882.                                       numOfCols: INTEGER; { Number of columns initially }
  1883.                                       rowHeight: INTEGER; { Row height, or zero for font height }
  1884.                                       colWidth: INTEGER; { Width of items in the columns }
  1885.                                       adornRows: BOOLEAN; { Adornment for Rows? }
  1886.                                       adornCols: BOOLEAN; { Adornment for Columns? }
  1887.                                       rowInset: INTEGER; { horizontal space between cells }
  1888.                                       colInset: INTEGER; { vertical space between cells }
  1889.                                       singleSelection: BOOLEAN; { single cell selection? }
  1890.                                       itsTextStyle: TextStyle); { size, color, etc. font info }
  1891.  
  1892.     BEGIN
  1893.     fTextStyle := itsTextStyle;
  1894.  
  1895.     SetUpFont;
  1896.     IF rowHeight = 0 THEN
  1897.         rowHeight := fLineHeight + rowInset;
  1898.  
  1899.     IGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet, numOfRows,
  1900.               numOfCols, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset,
  1901.               singleSelection);
  1902.  
  1903.     IF (fNumOfCols = 1) & (fSizeDeterminer[h] <> sizeFixed) & (GetColWidth(1) = 0) & (fSuperView <>
  1904.        NIL) THEN
  1905.         SetColWidth(1, fNumOfCols, fSuperView.fSize.h);
  1906.     END;
  1907.  
  1908. {--------------------------------------------------------------------------------------------------}
  1909. {$S GVOpen}
  1910.  
  1911. PROCEDURE TTextGridView.IRes(itsDocument: TDocument;
  1912.                              itsSuperView: TView;
  1913.                              VAR itsParams: Ptr); OVERRIDE;
  1914.  
  1915.     VAR
  1916.         itsTextStyle:        TextStyle;
  1917.  
  1918.     BEGIN
  1919.     { The ancestor will need to focus when adding rows or columns.
  1920.     Get the information necessary to focus since this class sets textStyle when focusing }
  1921.     fTextStyle := gSystemStyle;                         { Put in safe state }
  1922.  
  1923.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1924.  
  1925.     WITH TextGridViewTemplatePtr(itsParams)^ DO
  1926.         BEGIN
  1927.         SetTextStyle(itsTextStyle, GetFontNum(itsFontName), itsFontFace, itsFontSize, itsFontColor);
  1928.         fTextStyle := itsTextStyle;
  1929.         END;
  1930.  
  1931.     SetUpFont;
  1932.  
  1933.     IF fNumOfRows > 0 THEN
  1934.         IF GetRowHeight(1) = 0 THEN                     { set row height from font }
  1935.             SetRowHeight(1, fNumOfRows, fLineHeight + fRowInset);
  1936.  
  1937.     IF (fNumOfCols = 1) & (fSizeDeterminer[h] <> sizeFixed) & (GetColWidth(1) = 0) THEN
  1938.         SetColWidth(1, fNumOfCols, fSize.h);
  1939.  
  1940.     OffsetPtrWStr(itsParams, SIZEOF(TextGridViewTemplate));
  1941.     END;
  1942.  
  1943. {--------------------------------------------------------------------------------------------------}
  1944. {$S GVNonRes}
  1945.  
  1946. PROCEDURE TTextGridView.WRes(theResource: ViewRsrcHndl;
  1947.                              VAR itsParams: Ptr); OVERRIDE;
  1948.  
  1949.     VAR
  1950.         theSize:            INTEGER;
  1951.         theFont:            Str255;
  1952.         tgPtr:                TextGridViewTemplatePtr;
  1953.  
  1954.     BEGIN
  1955.     INHERITED WRes(theResource, itsParams);
  1956.  
  1957.     theSize := fTextStyle.tsSize;
  1958.     GetPortFontInfo(fTextStyle.tsFont, theFont, theSize);
  1959.  
  1960.     tgPtr := TextGridViewTemplatePtr(ExpandPtrWStr(theResource, itsParams,
  1961.                                                    SIZEOF(TextGridViewTemplate), LENGTH(theFont)));
  1962.  
  1963.     WITH tgPtr^, fTextStyle DO
  1964.         BEGIN
  1965.         itsFontFace := tsFace;
  1966.         itsFontSize := theSize;
  1967.         itsFontColor := tsColor;
  1968.         { itsFontName := theFont; }
  1969.         END;
  1970.     CopyStr255(theFont, PRStr(tgPtr^.itsFontName));
  1971.     END;
  1972.  
  1973. {--------------------------------------------------------------------------------------------------}
  1974. {$S GVNonRes}
  1975.  
  1976. PROCEDURE TTextGridView.WriteRes(theResource: ViewRsrcHndl;
  1977.                                  VAR itsParams: Ptr); OVERRIDE;
  1978.  
  1979.     BEGIN
  1980.     gWResSignature := 'txtg'; gWResType := 'TTextGridView';
  1981.     WRes(theResource, itsParams);
  1982.     END;
  1983.  
  1984. {--------------------------------------------------------------------------------------------------}
  1985. {$S GVRes}
  1986.  
  1987. PROCEDURE TTextGridView.DrawCell(aCell: GridCell;
  1988.                                  aQDRect: Rect); OVERRIDE;
  1989.  
  1990.     VAR
  1991.         theText:            Str255;
  1992.  
  1993.     BEGIN
  1994.     GetText(aCell, theText);
  1995.  
  1996.     IF (GetColWidth(aCell.h) > 0) THEN
  1997.         MADrawString(@theText, aQDRect, teJustSystem);
  1998.     END;
  1999.  
  2000. {--------------------------------------------------------------------------------------------------}
  2001. {$S GVRes}
  2002.  
  2003. FUNCTION TTextGridView.Focus: BOOLEAN; OVERRIDE;
  2004.  
  2005.     BEGIN
  2006.     IF INHERITED Focus THEN
  2007.         BEGIN
  2008.         SetPen;
  2009.         Focus := TRUE;
  2010.         END
  2011.     ELSE
  2012.         Focus := FALSE;
  2013.     END;
  2014.  
  2015. {--------------------------------------------------------------------------------------------------}
  2016. {$S GVOpen}
  2017.  
  2018. PROCEDURE TTextGridView.SetUpFont;
  2019.  
  2020.     VAR
  2021.         savedPort:            GrafPtr;
  2022.         theFontInfo:        FontInfo;
  2023.  
  2024.     BEGIN
  2025.     GetPort(savedPort);
  2026.     SetPort(gWorkPort);
  2027.  
  2028.     SetPen;
  2029.     GetFontInfo(theFontInfo);
  2030.  
  2031.     SetPort(savedPort);
  2032.  
  2033.     WITH theFontInfo DO
  2034.         BEGIN
  2035.         fLineHeight := ascent + descent + leading;
  2036.         fLineAscent := ascent + (leading DIV 2);
  2037.         END;
  2038.  
  2039.     END;
  2040.  
  2041. {--------------------------------------------------------------------------------------------------}
  2042. {$S GVRes}
  2043.  
  2044. PROCEDURE TTextGridView.SetPen;
  2045.  
  2046.     VAR
  2047.         itsTextStyle:        TextStyle;
  2048.  
  2049.     BEGIN
  2050.     itsTextStyle := fTextStyle;
  2051.     SetPortTextStyle(itsTextStyle);
  2052.     PenNormal;
  2053.     END;
  2054.  
  2055. {--------------------------------------------------------------------------------------------------}
  2056. {$S GVRes}
  2057.  
  2058. PROCEDURE TTextGridView.GetText(aCell: GridCell;
  2059.                                 VAR aString: Str255);
  2060.  
  2061.     BEGIN
  2062.     { MUST be overridden! }
  2063.  
  2064.     {$IFC qDebug}
  2065.     Writeln('TTextGridView: GetText MUST be OVERRIDDEN!');
  2066.     {$ENDC qDebug}
  2067.     END;
  2068.  
  2069. {--------------------------------------------------------------------------------------------------}
  2070. {$S GVFields}
  2071.  
  2072. PROCEDURE TTextGridView.Fields(PROCEDURE DoToField(fieldName: Str255;
  2073.                                                    fieldAddr: Ptr;
  2074.                                                    fieldType: INTEGER)); OVERRIDE;
  2075.  
  2076.     BEGIN
  2077.     DoToField('TTextGridView', NIL, bClass);
  2078.     DoToField('fLineHeight', @fLineHeight, bInteger);
  2079.     DoToField('fLineAscent', @fLineAscent, bInteger);
  2080.     {$Push} {$H-}
  2081.     TextStyleFields('fTextStyle', fTextStyle, DoToField);
  2082.     {$Pop}
  2083.  
  2084.     INHERITED Fields(DoToField);
  2085.     END;
  2086.  
  2087. {--------------------------------------------------------------------------------------------------}
  2088. {$S GVOpen}
  2089.  
  2090. PROCEDURE TTextListView.ITextListView(itsDocument: TDocument; { Its document }
  2091.                                       itsSuperView: TView; { Its parent view }
  2092.                                       itsLocation: VPoint; { Top, Left in parent's coords }
  2093.                                       itsSize: VPoint;
  2094.                                       itsHSizeDet, itsVSizeDet: SizeDeterminer; { Size determiners }
  2095.                                       numOfItems: INTEGER; { Number of items initially }
  2096.                                       rowHeight: INTEGER; { Row height, or zero for font height }
  2097.                                       colWidth: INTEGER; { Width of items in the columns }
  2098.                                       adornRows: BOOLEAN; { Draw the row adornments? }
  2099.                                       adornCols: BOOLEAN; { Draw the col adornment? }
  2100.                                       rowInset: INTEGER; { Amount to inset the rows }
  2101.                                       colInset: INTEGER; { Amount to inset the column }
  2102.                                       singleSelection: BOOLEAN; { single cell selection? }
  2103.                                       itsTextStyle: TextStyle); { size, color, etc. font info }
  2104.  
  2105.     BEGIN
  2106.     ITextGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet,
  2107.                   numOfItems, 1, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset,
  2108.                   singleSelection, itsTextStyle);
  2109.     END;
  2110.  
  2111. {--------------------------------------------------------------------------------------------------}
  2112. {$S GVNonRes}
  2113.  
  2114. PROCEDURE TTextListView.WriteRes(theResource: ViewRsrcHndl;
  2115.                                  VAR itsParams: Ptr); OVERRIDE;
  2116.  
  2117.     BEGIN
  2118.     gWResSignature := 'lstg'; gWResType := 'TTextListView';
  2119.     WRes(theResource, itsParams);
  2120.     END;
  2121.  
  2122. {--------------------------------------------------------------------------------------------------}
  2123. {$S GVRes}
  2124.  
  2125. PROCEDURE TTextListView.AllItemsDo(PROCEDURE DoToItem(anItem: INTEGER));
  2126.  
  2127.     BEGIN
  2128.     EachItemDo(1, fNumOfRows, DoToItem);
  2129.     END;
  2130.  
  2131. {--------------------------------------------------------------------------------------------------}
  2132. {$S GVRes}
  2133.  
  2134. FUNCTION TTextListView.CanSelectCell(aCell: GridCell): BOOLEAN; OVERRIDE;
  2135.  
  2136.     BEGIN
  2137.     CanSelectCell := INHERITED CanSelectCell(aCell) & CanSelectItem(aCell.v);
  2138.     END;
  2139.  
  2140. {--------------------------------------------------------------------------------------------------}
  2141. {$S GVRes}
  2142.  
  2143. FUNCTION TTextListView.CanSelectItem(anItem: INTEGER): BOOLEAN;
  2144.  
  2145.     BEGIN
  2146.     CanSelectItem := (anItem >= 1) & (anItem <= fNumOfRows);
  2147.     END;
  2148.  
  2149. {--------------------------------------------------------------------------------------------------}
  2150. {$S GVNonRes}
  2151.  
  2152. PROCEDURE TTextListView.DelItemAt(anItem: INTEGER;
  2153.                                   numOfItems: INTEGER);
  2154.  
  2155.     BEGIN
  2156.     DelRowAt(anItem, numOfItems);
  2157.     END;
  2158.  
  2159. {--------------------------------------------------------------------------------------------------}
  2160. {$S GVNonRes}
  2161.  
  2162. PROCEDURE TTextListView.DelItemFirst(numOfItems: INTEGER);
  2163.  
  2164.     BEGIN
  2165.     DelItemAt(1, numOfItems);
  2166.     END;
  2167.  
  2168. {--------------------------------------------------------------------------------------------------}
  2169. {$S GVNonRes}
  2170.  
  2171. PROCEDURE TTextListView.DelItemLast(numOfItems: INTEGER);
  2172.  
  2173.     BEGIN
  2174.     DelItemAt(fNumOfRows - numOfItems + 1, numOfItems);
  2175.     END;
  2176.  
  2177. {--------------------------------------------------------------------------------------------------}
  2178. {$S GVRes}
  2179.  
  2180. PROCEDURE TTextListView.EachItemDo(start, stop: INTEGER;
  2181.                                    PROCEDURE DoToItem(anItem: INTEGER));
  2182.  
  2183.     VAR
  2184.         i:                    INTEGER;
  2185.  
  2186.     BEGIN
  2187.     FOR i := start TO stop DO
  2188.         DoToItem(i);
  2189.     END;
  2190.  
  2191. {--------------------------------------------------------------------------------------------------}
  2192. {$S GVRes}
  2193.  
  2194. PROCEDURE TTextListView.EachSelectedItemDo(PROCEDURE
  2195.                                            DoToItem(anItem: INTEGER));
  2196.  
  2197.     PROCEDURE DoToCell(aCell: GridCell);
  2198.  
  2199.         BEGIN
  2200.         DoToItem(aCell.v);
  2201.         END;
  2202.  
  2203.     BEGIN
  2204.     EachInRgn(fSelections, DoToCell);
  2205.     END;
  2206.  
  2207. {--------------------------------------------------------------------------------------------------}
  2208. {$S GVRes}
  2209.  
  2210. FUNCTION TTextListView.FirstSelectedItem: INTEGER;
  2211.  
  2212.     VAR
  2213.         aGridCell:            GridCell;
  2214.  
  2215.     BEGIN
  2216.     aGridCell := FirstSelectedCell;
  2217.     FirstSelectedItem := aGridCell.v;
  2218.     END;
  2219.  
  2220. {--------------------------------------------------------------------------------------------------}
  2221. {$S GVRes}
  2222.  
  2223. FUNCTION TTextListView.GetItemHeight(anItem: INTEGER): INTEGER;
  2224.  
  2225.     BEGIN
  2226.     GetItemHeight := GetRowHeight(anItem);
  2227.     END;
  2228.  
  2229. {--------------------------------------------------------------------------------------------------}
  2230. {$S GVRes}
  2231.  
  2232. FUNCTION TTextListView.GetItemWidth: INTEGER;
  2233.  
  2234.     BEGIN
  2235.     GetItemWidth := GetColWidth(1);
  2236.     END;
  2237.  
  2238. {--------------------------------------------------------------------------------------------------}
  2239. {$S GVRes}
  2240.  
  2241. PROCEDURE TTextListView.GetItemText(anItem: INTEGER;
  2242.                                     VAR aString: Str255);
  2243.  
  2244.     BEGIN
  2245.     { MUST be overridden !!! }
  2246.  
  2247.     {$IFC qDebug}
  2248.     Writeln('TTextListView: GetItemText MUST be OVERRIDDEN!');
  2249.     {$ENDC qDebug}
  2250.  
  2251.     END;
  2252.  
  2253. {--------------------------------------------------------------------------------------------------}
  2254. {$S GVRes}
  2255.  
  2256. PROCEDURE TTextListView.GetText(aCell: GridCell;
  2257.                                 VAR aString: Str255); OVERRIDE;
  2258.  
  2259.     BEGIN
  2260.     GetItemText(aCell.v, aString);
  2261.     END;
  2262.  
  2263. {--------------------------------------------------------------------------------------------------}
  2264. {$S GVRes}
  2265.  
  2266. PROCEDURE TTextListView.InsItemBefore(anItem: INTEGER;
  2267.                                       numOfItems: INTEGER);
  2268.  
  2269.     BEGIN
  2270.     InsRowBefore(anItem, numOfItems, fLineHeight + fRowInset);
  2271.     END;
  2272.  
  2273. {--------------------------------------------------------------------------------------------------}
  2274. {$S GVRes}
  2275.  
  2276. PROCEDURE TTextListView.InsItemFirst(numOfItems: INTEGER);
  2277.  
  2278.     BEGIN
  2279.     InsItemBefore(1, numOfItems);
  2280.     END;
  2281.  
  2282. {--------------------------------------------------------------------------------------------------}
  2283. {$S GVRes}
  2284.  
  2285. PROCEDURE TTextListView.InsItemLast(numOfItems: INTEGER);
  2286.  
  2287.     BEGIN
  2288.     InsItemBefore(fNumOfRows + 1, numOfItems);
  2289.     END;
  2290.  
  2291. {--------------------------------------------------------------------------------------------------}
  2292. {$S GVRes}
  2293.  
  2294. PROCEDURE TTextListView.InvalidateItem(anItem: INTEGER);
  2295.  
  2296.     VAR
  2297.         aCell:                GridCell;
  2298.  
  2299.     BEGIN
  2300.     aCell.h := 1;
  2301.     aCell.v := anItem;
  2302.     InvalidateCell(aCell);
  2303.     END;
  2304.  
  2305. {--------------------------------------------------------------------------------------------------}
  2306. {$S GVRes}
  2307.  
  2308. FUNCTION TTextListView.IsItemSelected(anItem: INTEGER): BOOLEAN;
  2309.  
  2310.     VAR
  2311.         aCell:                GridCell;
  2312.  
  2313.     BEGIN
  2314.     aCell.h := 1;
  2315.     aCell.v := anItem;
  2316.     IsItemSelected := IsCellSelected(aCell);
  2317.     END;
  2318.  
  2319. {--------------------------------------------------------------------------------------------------}
  2320. {$S GVRes}
  2321.  
  2322. FUNCTION TTextListView.LastSelectedItem: INTEGER;
  2323.  
  2324.     VAR
  2325.         aGridCell:            GridCell;
  2326.  
  2327.     BEGIN
  2328.     aGridCell := LastSelectedCell;
  2329.     LastSelectedItem := aGridCell.v;
  2330.     END;
  2331.  
  2332. {--------------------------------------------------------------------------------------------------}
  2333. {$S GVNonRes}
  2334.  
  2335. PROCEDURE TTextListView.Resize(width, height: VCoordinate;
  2336.                                invalidate: BOOLEAN); OVERRIDE;
  2337.  
  2338.     BEGIN
  2339.     INHERITED Resize(width, height, invalidate);
  2340.     IF fNumOfCols = 1 THEN
  2341.         BEGIN
  2342.         fColWidths.fTotal := fColWidths.fTotal - fColWidths.fChunks^^[0].value + width;
  2343.         fColWidths.fChunks^^[0].value := width;
  2344.         END;
  2345.     END;
  2346.  
  2347. {--------------------------------------------------------------------------------------------------}
  2348. {$S GVRes}
  2349.  
  2350. PROCEDURE TTextListView.SelectCell(theCell: GridCell;
  2351.                                    extendSelection, highlight, select: BOOLEAN); OVERRIDE;
  2352.  
  2353.     BEGIN
  2354.     SelectItem(theCell.v, extendSelection, highlight, select);
  2355.     END;
  2356.  
  2357. {--------------------------------------------------------------------------------------------------}
  2358. {$S GVRes}
  2359.  
  2360. PROCEDURE TTextListView.SelectItem(anItem: INTEGER;
  2361.                                    extendSelection, highlight, select: BOOLEAN);
  2362.  
  2363.     VAR
  2364.         aCell:                GridCell;
  2365.  
  2366.     BEGIN
  2367.     aCell.v := anItem;
  2368.     aCell.h := Min(1, anItem);
  2369.  
  2370.     INHERITED SelectCell(aCell, extendSelection, highlight, select);
  2371.     END;
  2372.  
  2373. {--------------------------------------------------------------------------------------------------}
  2374. {$S GVNonRes}
  2375.  
  2376. PROCEDURE TTextListView.SetItemHeight(anItem: INTEGER;
  2377.                                       numOfItems: INTEGER;
  2378.                                       aHeight: INTEGER);
  2379.  
  2380.     BEGIN
  2381.     SetRowHeight(anItem, numOfItems, aHeight);
  2382.     END;
  2383.  
  2384. {--------------------------------------------------------------------------------------------------}
  2385. {$S GVNonRes}
  2386.  
  2387. PROCEDURE TTextListView.SetItemWidth(aWidth: INTEGER);
  2388.  
  2389.     BEGIN
  2390.     SetColWidth(1, 1, aWidth);
  2391.     END;
  2392.  
  2393. {--------------------------------------------------------------------------------------------------}
  2394. {$S GVFields}
  2395.  
  2396. PROCEDURE TTextListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  2397.                                                    fieldAddr: Ptr;
  2398.                                                    fieldType: INTEGER)); OVERRIDE;
  2399.  
  2400.     BEGIN
  2401.     DoToField('TTextListView', NIL, bClass);
  2402.     INHERITED Fields(DoToField);
  2403.     END;
  2404.  
  2405. {--------------------------------------------------------------------------------------------------}
  2406. {$S GVSelCommand}
  2407.  
  2408. PROCEDURE TCellSelectCommand.ICellSelectCommand(itsView: TGridView;
  2409.                                                 theShiftKey, theCmdKey: BOOLEAN);
  2410.  
  2411.     VAR
  2412.         fi:                 FailInfo;
  2413.  
  2414.     PROCEDURE HandleFailure(error: OSErr;
  2415.                             message: LONGINT);
  2416.  
  2417.         BEGIN
  2418.         Free;
  2419.         END;
  2420.  
  2421.     BEGIN
  2422.     fThisSelection := NIL;
  2423.     fPrevSelection := NIL;
  2424.     fDifference := NIL;
  2425.     fGridView := NIL;
  2426.  
  2427.     fShiftKey := theShiftKey;
  2428.     fCmdKey := theCmdKey;
  2429.  
  2430.     ICommand(cNoCommand, NIL, itsView, itsView.GetScroller(FALSE));
  2431.     fCanUndo := FALSE;
  2432.     fCausesChange := FALSE;
  2433.     fViewConstrain := FALSE;
  2434.  
  2435.     fGridView := itsView;
  2436.  
  2437.     fAnchorCell := gZeroPt;                             { At least set it to something }
  2438.     fPrevCell.h := - 1;                                 { ??? Blech! there must be a better way }
  2439.     fPrevCell.v := - 1;                                 { ??? Blech! there must be a better way }
  2440.  
  2441.     CatchFailures(fi, HandleFailure);
  2442.     fPrevSelection := MakeNewRgn;
  2443.     CopyRgn(fGridView.fSelections, fPrevSelection);
  2444.     fThisSelection := fGridView.fHLRegion;
  2445.     SetEmptyRgn(fThisSelection);
  2446.     fDifference := MakeNewRgn;
  2447.     Success(fi);
  2448.     END;
  2449.  
  2450. {--------------------------------------------------------------------------------------------------}
  2451. {$S GVDoCommand}
  2452.  
  2453. PROCEDURE TCellSelectCommand.Free; OVERRIDE;
  2454.  
  2455.     BEGIN
  2456.     IF fPrevSelection <> NIL THEN
  2457.         DisposeRgn(fPrevSelection);
  2458.     fPrevSelection := NIL;
  2459.  
  2460.     IF fDifference <> NIL THEN
  2461.         DisposeRgn(fDifference);
  2462.     fDifference := NIL;
  2463.  
  2464.     fThisSelection := NIL;                                { I don't own it so I don't dispose it. But,
  2465.                                                          I sure don't need a reference to it any
  2466.                                                          more. }
  2467.  
  2468.     INHERITED Free;
  2469.     END;
  2470.  
  2471. {--------------------------------------------------------------------------------------------------}
  2472. {$S GVDoCommand}
  2473.  
  2474. PROCEDURE TCellSelectCommand.ComputeAnchorCell(VAR clickedCell: GridCell);
  2475.  
  2476.     BEGIN
  2477.     fAnchorCell := clickedCell;
  2478.  
  2479.     IF fShiftKey & (NOT EmptyRgn(fPrevSelection)) THEN
  2480.         WITH fPrevSelection^^.rgnBBox DO
  2481.             BEGIN
  2482.             IF fAnchorCell.h >= left THEN
  2483.                 fAnchorCell.h := left
  2484.             ELSE
  2485.                 fAnchorCell.h := right - 1;
  2486.             IF fAnchorCell.v >= top THEN
  2487.                 fAnchorCell.v := top
  2488.             ELSE
  2489.                 fAnchorCell.v := bottom - 1;
  2490.             END;
  2491.     END;
  2492.  
  2493. {--------------------------------------------------------------------------------------------------}
  2494. {$S GVDoCommand}
  2495.  
  2496. PROCEDURE TCellSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell);
  2497.  
  2498.     VAR
  2499.         r:                    Rect;
  2500.  
  2501.     BEGIN
  2502.     IF fGridView.CanSelectCell(clickedCell) THEN
  2503.         BEGIN
  2504.         IF fGridView.fSingleSelection | (NOT fShiftKey) THEN
  2505.             SetRect(r, clickedCell.h, clickedCell.v, clickedCell.h + 1, clickedCell.v + 1)
  2506.         ELSE
  2507.             BEGIN
  2508.             Pt2Rect(fAnchorCell, clickedCell, r);
  2509.             r.right := r.right + 1;
  2510.             r.bottom := r.bottom + 1;
  2511.             END;
  2512.         RectRgn(fThisSelection, r);
  2513.         IF fCmdKey & (NOT fGridView.fSingleSelection) THEN
  2514.             IF fDeselecting THEN
  2515.                 DiffRgn(fPrevSelection, fThisSelection, fThisSelection)
  2516.             ELSE
  2517.                 UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
  2518.         END;
  2519.     END;
  2520.  
  2521. {--------------------------------------------------------------------------------------------------}
  2522. {$S GVDoCommand}
  2523.  
  2524. PROCEDURE TCellSelectCommand.HighlightNewSelection;
  2525.  
  2526.     BEGIN
  2527.     { Turn off previously selected cells }
  2528.     DiffRgn(fPrevSelection, fThisSelection, fDifference);
  2529.     fGridView.HighlightCells(fDifference, fGridView.fHLDesired, hlOFF);
  2530.  
  2531.     { Turn on newly selected cells}
  2532.     DiffRgn(fThisSelection, fPrevSelection, fDifference);
  2533.     fGridView.HighlightCells(fDifference, hlOFF, fGridView.fHLDesired);
  2534.     END;
  2535.  
  2536. {--------------------------------------------------------------------------------------------------}
  2537. {$S GVDoCommand}
  2538.  
  2539. PROCEDURE TCellSelectCommand.TrackFeedback(anchorPoint, nextPoint: VPoint;
  2540.                                            turnItOn, mouseDidMove: BOOLEAN); OVERRIDE;
  2541.  
  2542.     BEGIN
  2543.     END;
  2544.  
  2545. {--------------------------------------------------------------------------------------------------}
  2546. {$S GVDoCommand}
  2547.  
  2548. FUNCTION TCellSelectCommand.TrackMouse(aTrackPhase: TrackPhase;
  2549.                                        VAR anchorPoint, previousPoint, nextPoint: VPoint;
  2550.                                        mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  2551.  
  2552.     VAR
  2553.         clickedCell:        GridCell;
  2554.         viewExtent:         VRect;
  2555.         clippedPoint:        VPoint;
  2556.  
  2557.     BEGIN
  2558.     IF mouseDidMove THEN
  2559.         BEGIN
  2560.         fGridView.GetExtent(viewExtent);
  2561.         clippedPoint := nextPoint;
  2562.         PinVRect(viewExtent, clippedPoint);
  2563.         clickedCell := fGridView.VPointToCell(clippedPoint);
  2564.         IF aTrackPhase = TrackPress THEN
  2565.             BEGIN
  2566.             ComputeAnchorCell(clickedCell);
  2567.             IF fCmdKey THEN
  2568.                 fDeselecting := PtInRgn(fAnchorCell, fGridView.fSelections);
  2569.             END;
  2570.  
  2571.         IF LONGINT(clickedCell) <> LONGINT(fPrevCell) THEN
  2572.             BEGIN
  2573.             ComputeNewSelection(clickedCell);
  2574.             HighlightNewSelection;
  2575.  
  2576.             CopyRgn(fThisSelection, fPrevSelection);
  2577.             fPrevCell := clickedCell;
  2578.             END;
  2579.         END;
  2580.     TrackMouse := SELF;
  2581.     END;
  2582.  
  2583. {--------------------------------------------------------------------------------------------------}
  2584. {$S GVDoCommand}
  2585.  
  2586. PROCEDURE TCellSelectCommand.DoIt; OVERRIDE;
  2587.  
  2588.     BEGIN
  2589.     IF fGridView.fSingleSelection THEN
  2590.         fGridView.SelectCell(fThisSelection^^.rgnBBox.topLeft, kDontExtend, kDontHighlight, kSelect)
  2591.     ELSE
  2592.         fGridView.SetSelection(fThisSelection, kDontExtend, kDontHighlight, kSelect);
  2593.     END;
  2594.  
  2595. {--------------------------------------------------------------------------------------------------}
  2596. {$S GVFields}
  2597.  
  2598. PROCEDURE TCellSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2599.                                                         fieldAddr: Ptr;
  2600.                                                         fieldType: INTEGER)); OVERRIDE;
  2601.  
  2602.     BEGIN
  2603.     DoToField('TCellSelectCommand', NIL, bClass);
  2604.     DoToField('fGridView', @fGridView, bObject);
  2605.     DoToField('fShiftKey', @fShiftKey, bBoolean);
  2606.     DoToField('fCmdKey', @fCmdKey, bBoolean);
  2607.     DoToField('fDeselecting', @fDeselecting, bBoolean);
  2608.     DoToField('fAnchorCell', @fAnchorCell, bPoint);
  2609.     DoToField('fPrevCell', @fPrevCell, bPoint);
  2610.     DoToField('fThisSelection', @fThisSelection, bRgnHandle);
  2611.     DoToField('fPrevSelection', @fPrevSelection, bRgnHandle);
  2612.     DoToField('fDifference', @fDifference, bRgnHandle);
  2613.  
  2614.     INHERITED Fields(DoToField);
  2615.     END;
  2616.  
  2617. {--------------------------------------------------------------------------------------------------}
  2618. {$S GVDoCommand}
  2619.  
  2620. PROCEDURE TRCSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell); OVERRIDE;
  2621.  
  2622.     VAR
  2623.         r:                    Rect;
  2624.  
  2625.     BEGIN
  2626.     IF fGridView.CanSelectCell(clickedCell) THEN
  2627.         BEGIN
  2628.         IF fGridView.fSingleSelection THEN
  2629.             SetRect(r, clickedCell.h, clickedCell.v, clickedCell.h + 1, clickedCell.v + 1)
  2630.         ELSE
  2631.             BEGIN
  2632.             Pt2Rect(fAnchorCell, clickedCell, r);
  2633.             r.right := r.right + 1;
  2634.             r.bottom := r.bottom + 1;
  2635.             END;
  2636.         RectRgn(fThisSelection, r);
  2637.         IF fCmdKey & (NOT fGridView.fSingleSelection) THEN
  2638.             IF fDeselecting THEN
  2639.                 DiffRgn(fPrevSelection, fThisSelection, fThisSelection)
  2640.             ELSE
  2641.                 UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
  2642.         END;
  2643.     END;
  2644.  
  2645. {--------------------------------------------------------------------------------------------------}
  2646. {$S GVDoCommand}
  2647.  
  2648. FUNCTION TRCSelectCommand.TrackMouse(aTrackPhase: TrackPhase;
  2649.                                      VAR anchorPoint, previousPoint, nextPoint: VPoint;
  2650.                                      mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  2651.  
  2652.     VAR
  2653.         clickedCell:        GridCell;
  2654.         viewExtent:         VRect;
  2655.         clippedPoint:        VPoint;
  2656.  
  2657.     BEGIN
  2658.     IF mouseDidMove THEN
  2659.         BEGIN
  2660.         fGridView.GetExtent(viewExtent);
  2661.         clippedPoint := nextPoint;
  2662.         PinVRect(viewExtent, clippedPoint);
  2663.         clickedCell := fGridView.VPointToCell(clippedPoint);
  2664.         IF aTrackPhase = TrackPress THEN
  2665.             BEGIN
  2666.             ComputeAnchorCell(clickedCell);
  2667.             IF fCmdKey THEN
  2668.                 fDeselecting := PtInRgn(fAnchorCell, fGridView.fSelections);
  2669.             END;
  2670.  
  2671.         IF LONGINT(clickedCell) <> LONGINT(fPrevCell) THEN
  2672.             BEGIN
  2673.             IF (NOT fShiftKey) & (aTrackPhase <> TrackPress) THEN
  2674.                 BEGIN
  2675.                 ComputeAnchorCell(clickedCell);
  2676.                 IF fCmdKey THEN
  2677.                     fDeselecting := PtInRgn(fAnchorCell, fGridView.fSelections);
  2678.                 END;
  2679.             ComputeNewSelection(clickedCell);
  2680.             HighlightNewSelection;
  2681.  
  2682.             CopyRgn(fThisSelection, fPrevSelection);
  2683.             fPrevCell := clickedCell;
  2684.             END;
  2685.         END;
  2686.     TrackMouse := SELF;
  2687.     END;
  2688.  
  2689. {--------------------------------------------------------------------------------------------------}
  2690. {$S GVFields}
  2691.  
  2692. PROCEDURE TRCSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2693.                                                       fieldAddr: Ptr;
  2694.                                                       fieldType: INTEGER)); OVERRIDE;
  2695.  
  2696.     BEGIN
  2697.     DoToField('TRCSelectCommand', NIL, bClass);
  2698.     INHERITED Fields(DoToField);
  2699.     END;
  2700.  
  2701. {--------------------------------------------------------------------------------------------------}
  2702. {$S GVSelCommand}
  2703.  
  2704. PROCEDURE TRowSelectCommand.IRowSelectCommand(itsView: TGridView;
  2705.                                               theShiftKey, theCmdKey: BOOLEAN);
  2706.  
  2707.     BEGIN
  2708.     ICellSelectCommand(itsView, theShiftKey, theCmdKey);
  2709.     END;
  2710.  
  2711. {--------------------------------------------------------------------------------------------------}
  2712. {$S GVDoCommand}
  2713.  
  2714. PROCEDURE TRowSelectCommand.ComputeAnchorCell(VAR clickedCell: GridCell); OVERRIDE;
  2715.  
  2716.     BEGIN
  2717.     INHERITED ComputeAnchorCell(clickedCell);
  2718.     fAnchorCell.h := 1;
  2719.     END;
  2720.  
  2721. {--------------------------------------------------------------------------------------------------}
  2722. {$S GVDoCommand}
  2723.  
  2724. PROCEDURE TRowSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell); OVERRIDE;
  2725.  
  2726.     BEGIN
  2727.     clickedCell.h := fGridView.fNumOfCols;
  2728.     INHERITED ComputeNewSelection(clickedCell);
  2729.     END;
  2730.  
  2731. {--------------------------------------------------------------------------------------------------}
  2732. {$S GVFields}
  2733.  
  2734. PROCEDURE TRowSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2735.                                                        fieldAddr: Ptr;
  2736.                                                        fieldType: INTEGER)); OVERRIDE;
  2737.  
  2738.     BEGIN
  2739.     DoToField('TRowSelectCommand', NIL, bClass);
  2740.     INHERITED Fields(DoToField);
  2741.     END;
  2742.  
  2743. {--------------------------------------------------------------------------------------------------}
  2744. {$S GVSelCommand}
  2745.  
  2746. PROCEDURE TColumnSelectCommand.IColumnSelectCommand(itsView: TGridView;
  2747.                                                     theShiftKey, theCmdKey: BOOLEAN);
  2748.  
  2749.     BEGIN
  2750.     ICellSelectCommand(itsView, theShiftKey, theCmdKey);
  2751.     END;
  2752.  
  2753. {--------------------------------------------------------------------------------------------------}
  2754. {$S GVDoCommand}
  2755.  
  2756. PROCEDURE TColumnSelectCommand.ComputeAnchorCell(VAR clickedCell: GridCell); OVERRIDE;
  2757.  
  2758.     BEGIN
  2759.     INHERITED ComputeAnchorCell(clickedCell);
  2760.     fAnchorCell.v := 1;
  2761.     END;
  2762.  
  2763. {--------------------------------------------------------------------------------------------------}
  2764. {$S GVDoCommand}
  2765.  
  2766. PROCEDURE TColumnSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell); OVERRIDE;
  2767.  
  2768.     BEGIN
  2769.     clickedCell.v := fGridView.fNumOfRows;
  2770.     INHERITED ComputeNewSelection(clickedCell);
  2771.     END;
  2772.  
  2773. {--------------------------------------------------------------------------------------------------}
  2774. {$S GVFields}
  2775.  
  2776. PROCEDURE TColumnSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2777.                                                           fieldAddr: Ptr;
  2778.                                                           fieldType: INTEGER)); OVERRIDE;
  2779.  
  2780.     BEGIN
  2781.     DoToField('TColumnSelectCommand', NIL, bClass);
  2782.     INHERITED Fields(DoToField);
  2783.     END;
  2784.